1.一个类的生命周期。
1.加载
2.连接:验证、准备、解析
3.初始化
4.使用
5.卸载
有且仅有四种情况必须对类进行初始化:
1,new了一个实例对象 读取或设置类的静态变量 调用类的静态方法。
2.对类进行反射调用的时候。如果还没初始化必须先初始化。
3.当初始化一个类时,发现该类的父类还没有经过初始化。(接口除外)
4.当虚拟机启动时,用户需要指定一个要执行的主类。这个类初始化。
这四种场景成为对类的主动引用。被动引用:1.子类引用父类的静态变量,不会触发子类的初始化。2.数组引用。3.引用类中的静态常量。
类的加载过程。
1.加载(loading)(查找并添加类的二进制数据)
- 1.通过一个类的全限定名来获取定义此类的二进制字节流。
- 2.将这个字节流所代表的静态存储结构转换为方法区的运行时数据结构。
- 3.在java的堆中生成一个代表这个类的java.lang.Class 对象,作为方法区这些数据的访问入口。
2.验证(确保被加载类的正确性)(记忆方法格式》类》方法》引用)
- 1.文件格式验证:比如开头是否是0xcoffeebabe 版本号是否在当前虚拟机处理范围之类,常量池中的常量是否有不被支持的常量类型。就是保证输入的字节流能正确解析并存储与方法区之内,格式上符合描述一个java类型信息的要求。
- 2.元数据验证:对字节码描述的信息进行语义分析,以保证其描述的信息符合java语言的规范要求。比如这个类是否继承了被final修饰的类,这个类不是抽象类是否实现了父类的所有抽象方法。
- 3.字节码验证:对类的方法体进行验证分析,保证被校验类的方法运行时不会出现损害虚拟机安全的行为。
- 4.符号引用验证:保证解析动作能正常执行,比如符号引用中的通过字符串描述的全限定名能否找到对应的类,符号引用类中的类,字段,方法的访问性能否被当前类访问。
3.准备(在方法区中为类变量分配内存,并赋初始值)注意两点:
- 1.是为静态变量分配内存,不包括实例变量,实例变量会随着实例化时跟随对象在堆中分配内存。
- 2.赋初始值,比如int类型 是0 不是类中定义的数。类中定义的值会在初始化时赋值给类变量。
4.解析(把类中的符号引用转换为直接引用)
虚拟机将常量池内的符号引用替换为直接引用的过程。
个人理解
符号引用:符号引用是一组符号来描述所引用的目标对象,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可。符号引用与虚拟机实现的内存布局无关,引用的目标对象并不一定已经加载到内存中。
直接引用:直接引用可以是直接指向目标对象的指针(指向类变量,类方法)、相对偏移量(实例的变量)或是一个能间接定位到目标的句柄。直接引用是与虚拟机内存布局实现相关的,同一个符号引用在不同的虚拟机实例上翻译出来的直接引用一般不会相同,如果有了直接引用,那引用的目标必定已经在内存中存在
5.初始化(为类的静态变量赋予正确的初始值)四种情况一定会触发初始化。
类加载器和双亲委派模型。
一个类的唯一性是由加载它的类加载器和这个类的class文件一起确定的。
1.启动类加载器,由c++语言实现,是虚拟机自身的一部分。Bootstrap ClassLoader
2.剩余的类加载器都是继承自java.lang.ClassLoader类。
1.启动类加载器(Bootstrap ClassLoader):负责加载<JAVA_HOME>\lib 目录中的类
2.扩展类加载器(Extension ClassLoader ExtClassLoader):负责加载<JAVA_HOME>\lib\ext中的类。
3.应用程序类加载器(Application ClassLoader AppClassLoader):如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
双亲委派模型:模型要求除了bootstrap classloader外,其余类加载器都应有自己的父类加载器,而这种父子关系一般通过组合关系来实现
工作过程;当一个类加载器收到加载类的请求时,首先不会自己尝试加载类,而是将该请求委托给自己的父类加载器,层层委托后,所有的请求都会委托到顶层的启动类加载器去加载,当父类加载器反馈自己无法加载时(它负责的范围内没有找到所需类),子类加载器才会尝试加载该类。
模型的优点:java类随着它的类加载器一起具备了一种带有优先级的层次关系。1.防止类被重复的加载。2.防止api核心类库中的类被篡改。
自定义一个类加载器。核心方法loadClass 和 findClass
是否要破环双亲委派模型。不破坏,只写findClass 破环 loadClass也重写。
热修复的两大主流方案:1.阿里系的底层替换方案。2.腾讯系的类加载方案。
底层替换方案:从底层C的二进制来解决问题,这样做限制颇多,但时效性最好,加载轻快,立即见效;
类加载方案:从Java加载机制来解决问题,这样做时效性差,需要重新冷启动才能见效,但修复范围广,限制少;
网友评论