Class加载过程
一、Loading
-
加载是指通过动态计算来查找具有特定名称的类或接口类型的二进制形式的过程
-
LazyLoading五种情况
-
new、get-static、put-static、invoke-static指令,访问final变量除外
-
java.lang.reflect对类进行反射时调用
-
初始化子类的时候,父类首先初始化
-
虚拟机启动时。被执行的主类必须初始化
-
动态语言支持java.lang.invoke.MethodHandle解析的结果为REF>get-static、REF>put-static、REF>invoke-static的方法句柄时,该类必须初始化
-
-
CLassLoader源码解析
-
JIT编译器的工作模式
- 混合执行: 通过“-Xmixed”参数设定
- 编译执行: 通过“-Xint”参数设定
- 解释执行: 通过“-Xcomp”参数设定
- 检测热点代码:-XX:CompileThreshold=10000
-
自定义加载器
-
继承 ClassLoader
-
重写 findClass
- 通过ByteArrayOutputStream将本地的java文件转化为字节码文件
- 这一步可以进行字节码文件的加密操作
- 通过defineClass来调用本地方法将字节码文件转化为CLass
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; public class ClassLoadCustom extends ClassLoader{ public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException { ClassLoader classLoader = new ClassLoadCustom(); Class<?> clazz = classLoader.loadClass("cn.Custom"); Custom o = (Custom) clazz.newInstance(); System.out.println(o.test()); } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { File file =new File("E:/source-analysis/Java/JVM",name.replaceAll(".","/").concat(".class")); try { FileInputStream fis = new FileInputStream(file); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int len = 0; while ((len = fis.read()) !=0){ baos.write(len); } byte[] bytes = baos.toByteArray(); baos.close(); fis.close(); return defineClass(name,bytes,0,bytes.length); } catch (Exception e) { e.printStackTrace(); } return super.findClass(name); } }
public class Custom { public String test(){ return "classloader -> custom"; } }
- 通过ByteArrayOutputStream将本地的java文件转化为字节码文件
-
二、Linking
- verification(验证)
- 验证可确保类或接口的二进制表示在结构上正确
- preparation(准备)
- 准备工作包括
static
为类或接口创建字段(类变量和常量)
- 准备工作包括
- resolution of symbolic references (解析符号引用)
- 将类、方法、属性等符号引用解析为直接引用
- 常量池中的各种符号引用解析为指针、偏移量等内存地址的直接引用
三、Initialzing
- 类或接口类型T将在以下任何一种首次出现之前立即初始化:
- T is a class and an instance of T is created
- A
static
method declared by T is invoked - A
static
field declared by T is assigned - A
static
field declared by T is used and the field is not a constant variable
- 该过程假定该
Class
对象已经过验证和准备,并且该Class
对象包含指示四种情况之一的状态:- 该
Class
对象已经过验证和准备,但尚未初始化。 - 该
Class
对象正在由某些特定的线程初始化T
。 - 该
Class
对象已完全初始化并可以使用。 - 该
Class
对象处于错误状态,可能是因为尝试了初始化而失败了。
- 该