1:类加载-初始化
-
加载过程
-
Loading
-
双亲委派,主要出于安全来考虑
-
LazyLoading 五种情况
-
–new getstatic putstatic invokestatic指令,访问final变量除外
–java.lang.reflect对类进行反射调用时
–初始化子类的时候,父类首先初始化
–虚拟机启动时,被执行的主类必须初始化
–动态语言支持java.lang.invoke.MethodHandle解析的结果为REF_getstatic REF_putstatic REF_invokestatic的方法句柄时,该类必须初始化
-
-
ClassLoader的源码
- findInCache 尝试从缓存中获取
- parent.loadClass 不断往上的尝试获取(双亲委派,自定义ClassLoader->AppClassLoader->ExtClasssLoader->BootStrapClassLoader)
- findClass() 模板方法中需要被覆盖的方法,用来扩展自定义的ClassLoader
-
自定义类加载器
- extends ClassLoader
- overwrite findClass() -> 最终调用:defineClass(byte[] -> Class clazz)
- 加密,可以用证书进行加解密,原理相对简单;无非就是对class文件进行证书加密,在定义的ClassLoader中对加密后的class文件进行解密;只要保证证书的安全即可
- 打破双亲委派
- 用super(parent)指定
- 双亲委派的打破
- 如何打破:重写loadClass()
- 何时打破过?
- JDK1.2之前,自定义ClassLoader都必须重写loadClass()
- ThreadContextClassLoader可以实现基础类调用实现类代码,通过thread.setContextClassLoader指定
- 热启动,热部署
- osgi tomcat 都有自己的模块指定classloader(可以加载同一类库的不同版本)
-
混合执行 编译执行 解释执行
- 检测热点代码(执行几次被认为是热点代码):-XX:CompileThreshold = 10000
-
-
Linking
- Verification
- 验证文件是否符合JVM规定
- Preparation
- 静态成员变量赋默认值
- Resolution
- 将类、方法、属性等符号引用解析为直接引用 常量池中的各种符号引用解析为指针、偏移量等内存地址的直接引用
- Verification
-
Initializing
- 调用类初始化代码 ,给静态成员变量赋初始值
-
-
小总结:
- load class
- 静态变量赋默认值
- 静态变量赋初始值
- new 对象
- 申请内存
- 成员变量赋默认值
- 成员变量赋初始值
- load class