JVM(3)—类加载子系统

JVM(3)—类加载子系统

类加载子系统负责从文件或者网络加载Class字节流,读取字节码中的信息,运行时存储到JVM内存中,任何Class字节流都要遵循JVM字节码规范。

类加载执行过程:1.加载。2.链接。3.初始化。

加载

  1. 读取字节码二进制流。
  2. 解析字节码二进制流的静态数据转换为运行时JVM方法区数据。
  3. 生成java.lang.Class对象,放入堆中,作为方法区的访问入口。
  4. 加载类过程中,父类先加载。

什么时候加载字节码?

  1. new实例化。 A a = new A()
  2. 反射。 Class.forName("")
  3. 子类加载时父类先加载。
  4. JVM启动时。包含main方法的主类。
  5. 1.7动态类型语言支持。

链接

  1. 验证:确保字节码符合虚拟机规范要求。

  1. 准备:为类变量static赋予初始值。
public class A{
 public static int a = 100;   
}
// 准备阶段 a = 0 ,初始化阶段 a = 100。
  1. 解析:将字节码符号引用转换为直接引用。包括类解析,字段解析,方法解析,接口解析。

即将字节码的静态字面关联(字符串,静态)转换为JVM内存中的动态指针关联(指针,动态)。

初始化

  1. 执行类构造器方法<clinit>()。

  2. <clinit>()方法用于完成类的初始化操作。

  3. <clinit>()方法由编译器自动生成。

  4. <clinit>()方法是对类(静态)变量赋值与执行static代码块。

  5. 子类执行<clinit>(),会先执行父类<clinit>()。

  6. 没有类(静态)变量和static代码块,就不会<clinit>()。

  7. <clinit>()执行会加同步锁,保证<clinit>()只执行一次。

类加载器

  1. 启动类加载器:C语言开发。加载Java核心类库。基于沙箱机制,只加载java、javax、sun包开头的类。
  2. 扩展类加载器:Java语言编写,由sun.misc.Launcher$ExtClassLoader实现。上级加载器为启动类加载器。
  3. 应用程序类加载器:Java语言编写,由sun.misc.Launcher$AppClassLoader实现。上级加载器为扩展类加载器。是默认的类加载器。

自定义类加载器

  1. 使用场景:字节码二进制流来自于网络,字节码文件不在指定的lib、ext、classpath路径下,需要对二进制流加工后才能得到字节码。
  2. Class实例在JVM中是全局唯一的吗?

不同的类加载器加载同一个Class字节码文件后,在JVM中产生的类对象是不同的。

同一个类加载器,Class实例在JVM中才是全局唯一。

双亲委派机制

加载类时加载器逐级将加载任务向上委派至启动类加载器,然后逐级向下尝试加载,直至加载完成。

优点:保护了类不会被重复加载,禁止用户污染java开头的核心包。

package java;
public class Custom {
    public static void main(String[] args) {
        System.out.println("java");
    }
}
// 沙箱机制,以java开头的包将拒绝加载
java.lang.SecurityException: Prohibited package name: java
posted @ 2020-08-25 20:15  Baby丿太依赖  阅读(149)  评论(0)    收藏  举报