jvm 虚拟机加载机制

加载class 文件到内存

  1. 加载(三件事)
    1.1 这个文件在哪儿?它是jar 还是class 文件?
    java TestClass
    java -jar
    1.2 静态存储结构转化方法区的运行时数据结构
    jvm 运行时数据区

方法区:存放的是常量池和方法,
堆(heap):存放的是对象
1.3 java堆里面生成一个Class对象(相当于一个句柄),去访问方法区。

  1. 验证
    2.1 验证Class文件的标识:魔数Magic Number
    2.2 验证Class文件的版本号
    2.3 验证常量池(常量类型,常量类型数据结构是否正确、UTF8是否符合标准)
    2.4 Class文件的每个部分(字段表、方法表等)
    2.5 元数据验证(final验证、父类验证、继承验证)
    2.6 字节码验证(指令验证)
    2.7 符号引用验证(通过符号引用是否能找到字段、方法、类)

  2. 准备
    为类变量分配内存并且设置类变量的初始化阶段,只对static类变量进行内存分配。

   static int n=2; //初始化值是0,而不是2。因为这个时候还没执行任何java 方法.需要clinit去初始化
   static final int n=2;// 对应到常量池 ConstantValue,在准备阶段n必须被赋值为2。直接使用init初始化

类变量:一般称为静态变量
实例变量:当对象被实例化的时候,实例变量就跟着确定。随着对象的销毁而销毁。

  1. 解析
    对符号引用进行解析:把符号引用指向直接引用
    直接引用:指向目标的指针或者偏移量。
    符号引用=>直接引用。
    主要涉及:类、接口、字段、方法(接口、类)等。
    CONSTANT_Class_info
    CONSTANT_Fieldref_info
    CONSTANT_Methodref_info
    CONSTANT_InterfaceMethodref_info
    CONSTANT_MethodType_info
    CONSTANT_MethodHandler_info (方法=>vtable=>itable)
    CONSTANT_invokeDynamic_info
    匹配规则:简单名字(方法名)+描述符(参数+返回类型)同时满足,如 public String test(),简单名字就是test,描述符就是 ()String
    4.1 字段的解析
    在本类里面去找有没有匹配的字段=>如果类有接口,往上层接口找匹配的字段==>搜索父类
    eg:
          class A extends B implements C,D{
             private String str;//字段 
         }
    解析字段的顺序:A(分类)=>C,D(父接口)=>B(父类)=>Object(根类)
    如果找到了,但是没有权限:java.lang.IllegalAccessError
    如果失败(没找到):java.lang.NoSuchFieldError

4.2 类方法的解析
在本类里面去找有没有匹配的方法==>父类去找匹配的方法=>接口列表里面去找匹配方法(代表本类是一个抽象类,查找结束,抛出java.lang.AbstractMethodError异常)
如果找到了,但是没有权限:java.lang.IllegalAccessError
如果失败(没找到):java.lang.NoSuchFieldError
eg:

          class A extends B implements C,D{
             private void inc();//字段 
         }

4.3 接口方法的解析
在本类里面去找有没有匹配的方法=>父类接口中递归查找
如果失败(没找到):java.lang.NoSuchMethodError
5. 初始化
类的实例化构造器,
静态变量,静态块的初始化。如果没有静态变量或者静态块,则没有

Class A{
 static int i=2;
 static {
     System.out.println("");
  }
   int n;
}
原文地址:https://www.cnblogs.com/wanthune/p/12830618.html