当前位置: 首页 > 科技观察

面试官:说说类加载的过程

时间:2023-03-20 17:57:24 科技观察

Loading当我们要使用一个类的时候,我们需要通过ClassLoader将该类加载到内存中。“类加载阶段主要完成以下三件事。”通过完整的类名获取类名二进制流的二进制流解析类的二进制流为方法区的数据结构创建java.lang.Class类的实例,代表类型,作为在方法区访问该类的入口“通过全类名获取类的二进制流的方法有很多种”从zip压缩包中获取,从网络获取运行时计算,比如动态代理技术。..》对于非数组类型的加载阶段,可以使用Java虚拟机内置的类加载器来完成,也可以使用自定义类加载器来完成“链接”链接。这个阶段主要分为3个部分,验证,准备,分析,“验证”验证阶段主要是保证Class文件的格式正确,运行时不会对虚拟机造成伤害,里面有很多规则验证标记e的安全性,但大致分为以下四个阶段。》具体细节我就不详细解释了,大家可以参考《深入理解Java虚拟机》。本文倾向于做一个总结,把握一个类加载。整体过程不细说。“准备”准备阶段主要是为了为类的静态变量分配内存并将它们初始化为默认值。”常用数据类型默认值如下数据类型默认值byte(字节)0short(短)0int0long0Lfloat0.0fdouble0.0dbooleanfalsechar'\u0000'refe"rencenull"如果类静态变量的字段属性表中存在ConstantValue属性,则直接执行赋值语句。那么什么情况下类静态变量的字段属性表中存在ConstantValue属性呢?类静态变量是一种基本数据类型,被final修饰的类的静态变量是String类型,被final修饰,以字面值的形式赋值。为了方便查看Class文件的字节码,我在IDEA下载了一个插件jclasslibBytecodeviewer,使用下面的代码可以很方便的通过字节码验证publicclassPerson{privatestaticintage=10;privatestaticfinalintlength=160的形式;privatestaticfinalStringname="name";privatestaticfinalStringloc=newString("loc");}"所以length和name属性会在准备阶段赋值ConstantValue指定的值""那么age和loc属性会在哪个阶段赋值?是在初始化阶段,后面会详细介绍“解决”将类、接口、字段、方法的符号引用(在常量池中)转换为直接引用。Symbolicreferences:使用一组符号来描述被引用的目标直接引用;直接指向目标Join我写了一个类如下publicclassStudent{privateStringname;privateintage;publicStringgetName(){returnthis.name;}}以字段为例,name和age对应的对象并没有直接指向内存地址,但由字符串(即符号引用)描述。解析阶段就是将这些描述转化为直接指向目标的指针(即直接引用)来初始化“执行类静态成员变量赋值语句和静态代码块中的语句”。我们将上面的Student代码改成下面的形式);}publicStudent(){System.out.println("ConstructionFunction");}publicStringgetName(){returnthis.name;}}可以看到字节码包含3个方法,我们知道getName方法,执行什么逻辑从字节码中的方法中可以看出,方法的主要逻辑是调用父类的方法,给非静态成员变量赋值,执行构造代码块,并从字节码中执行构造函数“方法”。可以看出,该方法的主要逻辑是执行静态变量的赋值语句。在执行静态代码块中的语句时需要注意的一点是“Java虚拟机保证在子类的方法执行之前先执行父类的方法”。“理解和方法的作用还是很有必要的,因为有些面试题经常会问到静态代码块,构造代码块,以及构造函数的执行顺序。”我在这里直接总结结论。可以写个demo验证一下,“执行无继承顺序”静态代码块和静态成员变量,执行顺序由写的顺序决定(只会执行一次)构造代码块和非静态成员变量,执行顺序由构造函数“Executionorderwithinheritance”的书写顺序决定父类Static(静态代码块,静态成员变量),子类static(静态代码块,静态成员变量)(只执行一次)父类非静态(构造代码块,非静态成员变量),父类子类的非静态构造函数(构造代码块,非静态成员变量),子类的构造函数不仅在堆中卸载垃圾回收,而且在方法区。但是方法区回收类型数据的条件比较严格。下图就是一个例子。如果要回收方法区中的Simple类,需要保证堆中的Sample类及其子类已经被回收。加载Sample类的MyClassLoader已被回收。Sample类对应的Class对象已经被回收。可以看出,回收方法区类型数据的条件比较严格,但是效果微乎其微,所以有些垃圾回收器不会回收方法区的类型数据。类加载过程变量赋值过程总结转载本文请联系爪哇石塘公众号。