类加载
# 1 类的加载流程?
一个类的完整生命周期如下:
# 1.1 加载
类加载过程的第一步,主要完成3件事情:
1.通过全类名获取定义此类的二进制字节流。
2.将字节流信息转换成方法区的数据结构。
3.在方法区(元空间)内存中生成一个代表该类的Class对象,作为方法区这些数据的访问入口。
# 1.2 验证
确保加载的类符合JVM规范和安全,其实就是一个安全检查。
# 1.3 准备
为静态变量分配内存并赋予默认值的阶段。
# 1.4 解析
虚拟机将常量池内的符号引用替换为直接引用。
也就是得到类或者字段、方法在内存中的指针或者偏移量。
# 1.5 初始化
初始化静态变量为指定的值,执行静态代码块。
# 1.6 卸载
卸载类即该类的Class对象被GC。
卸载需要满足3个条件:
1.该类的所有实例对象已被GC。
2.该类没有在其他任何地方被引用。
3.该类的类加载器的实例已被GC。
所以,在JVM生命周期内,由jvm自带的类加载器加载的类是不会被卸载的。自定义的类加载器加载的类可能被卸载。
# 2 双亲委派机制
# 2.1 为什么要设计双亲委派机制?
1)沙箱安全机制:自己写的java.lang.String.class类不会被加载,这样便可以防止核心API库被随意篡改。
2)避免类的重复加载:当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次,保证被加载类的唯一性。
# 2.2 双亲委派的加载顺序?
双亲委派加载顺序为什么要从:
AppcClassLoader -> ExtClassLoader -> BootstrapClassLoader -> ExtClassLoader -> AppcClassLoader
为什么不直接:
BootstrapClassLoader -> ExtClassLoader -> AppcClassLoader
答:开发的应用中大部分用到的是appclassloader,第一次加载会麻烦一点,但是第二次加载如果发现该类已经加载过(c++实现),则直接用该加载器加载。
# 2.3 怎么实现自定义加载器?
继承ClassLoader,重写ClassLoader类中的findClass方法。
除了BootstrapClassLoader,其他类加载器均由Java实现且全部继承自java.lang.ClassLoader。
# 2.4 怎么打破双亲委派机制?
重写loadClass方法。