JVM中CLass的加载过程

目录

一、Loading

  • 加载是指通过动态计算来查找具有特定名称的类或接口类型的二进制形式的过程

  • LazyLoading五种情况

    1. new、get-static、put-static、invoke-static指令,访问final变量除外

    2. java.lang.reflect对类进行反射时调用

    3. 初始化子类的时候,父类首先初始化

    4. 虚拟机启动时。被执行的主类必须初始化

    5. 动态语言支持java.lang.invoke.MethodHandle解析的结果为REF>get-static、REF>put-static、REF>invoke-static的方法句柄时,该类必须初始化

  • CLassLoader源码解析

    1620802561378

  • JIT编译器的工作模式

    • 混合执行: 通过“-Xmixed”参数设定
    • 编译执行: 通过“-Xint”参数设定
    • 解释执行: 通过“-Xcomp”参数设定
    • 检测热点代码:-XX:CompileThreshold=10000
  • 自定义加载器

    1. 继承 ClassLoader

    2. 重写 findClass

      1. 通过ByteArrayOutputStream将本地的java文件转化为字节码文件
        1. 这一步可以进行字节码文件的加密操作
      2. 通过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";
          }
      }
      

二、Linking

  • verification(验证)
    • 验证可确保类或接口的二进制表示在结构上正确
  • preparation(准备)
    • 准备工作包括static为类或接口创建字段(类变量和常量)
  • resolution of symbolic references (解析符号引用)
    • 将类、方法、属性等符号引用解析为直接引用
      • 常量池中的各种符号引用解析为指针、偏移量等内存地址的直接引用

三、Initialzing

  • 类的初始化包括执行其静态初始化程序和static该类中声明的字段(类变量)的初始化程序

  • 类或接口类型T将在以下任何一种首次出现之前立即初始化:

    1. T is a class and an instance of T is created.

    2. A static method declared by T is invoked.

    3. A static field declared by T is assigned.

    4. A static field declared by T is used and the field is not a constant variable (§4.12.4)

  • 该过程假定该Class对象已经过验证和准备,并且该Class对象包含指示四种情况之一的状态:

    1. Class对象已经过验证和准备,但尚未初始化

    2. Class对象正在由某些特定的线程初始化T

    3. Class对象已完全初始化并可以使用

    4. Class对象处于错误状态,可能是因为尝试了初始化而失败了

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦