类加载子系统

1.类加载机制

在这里插入图片描述
JVM把class文件加载到内存,并对数据校验,解析和初始化,最终形成JVM可以直接使用的java类型的过程

1.1加载

将class文件字节码加载到内存,并将这些静态数据转化成方法区中运行时的二进制的数据结构,在堆中生成一个代表类的java.Lang.Class,作为方法区类数据的访问入口
在这里插入图片描述

1.2链接

将java的二进制代码合并到jvm的运行状态之中的过程

  • 验证:确保加载的类信息符合JVM规范,没有安全方面的问题。
  • 准备:正式为变量(static变呈)分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配
  • 解析:虚拟机常量池内的符号弓用替换为直接引用的过程

1.3初始化

  • 初始化阶段是执行类构造器clinit()方法的过程。类构适器clinit()是由编译器自动收集
    类中的所有类变量的赋值动作和静态语句块(static块)中的语法合并产生的·
  • 当初始化一个类的时候,如果发现其父类还没有进行过初始化、则需要先对其父类初始化
  • 虚拟机会保证一个类的cilnit()方法在多线程环境中被正确加锁和同步

发生类的初始化:类的主动引用

  • new一个类的对象
  • 调用类的静态成员(除了final常量)和静态方法
  • 使用java.lang.reflect包的方法对类进行反射调用
  • 运行main方法所在的类
  • 当初始化一个类的时候,如果发现其父类还没有进行过初始化、则需要先对其父类初始化

不会发生类的初始化:类的被动引用

  • 当访问一个静态域时,只有真正声明这个域的类才会被初始化。通过子类引用父的静态变量不导致子初始化
  • 沮叟类引用,不会岌此类的初始化
  • 引用此类常量不会触发此类的初始化(常量在编译阶段就存入调用类的常量池中了)
    在这里插入图片描述

2.深入类加载器

2.1.类加载器的层次结构

  • 引导类加载器:bootstrapClassLoader 虚拟机自带的加载器
    加载java核心库
    不继承java.lang.classLoader
    加载扩展类加载器和应用程序类加载器(系统类加载器)
    原生代码实现

  • 扩展类加载器:extClassLoader
    加载java扩展库
    加载应用程序类加载器 (系统类加载器)
    继承java.lang.classLoader

  • 应用程序类加载器(系统类加载器):systemClassLoader
    根据java应用的类路径加载java应用的类
    继承java.lang.classLoader

  • 自定义类加载器:

public class ClassLoaderTest {
    public static void main(String[] args) {

        //获取系统类加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2
        //获取扩展类加载器
        ClassLoader extClassLoader = systemClassLoader.getParent();
        System.out.println(extClassLoader);//sun.misc.Launcher$ExtClassLoader@677327b6


        //继续获取上层:获取不到引导类加载器,引导类加载器使用C语言和C++编写
        ClassLoader bootstrapClassLoader = extClassLoader.getParent();
        System.out.println(bootstrapClassLoader);//null


        //用户自定义类:默认使用系统类加载器加载
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
        System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2\

        //String类使用引导类加载器加载,系统的核心类库都是用引导类加载器加载
        ClassLoader classLoader1 = String.class.getClassLoader();
        System.out.println(classLoader1);
    }
}

2.2.双亲委托机制

Java虛拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象。而且加载某个类的class文件时,Java虚拟机采用的是双亲委派模式,即把请求交由父类处理,它是一种任务委派模式。
在这里插入图片描述
工作原理:
1、如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行;
2、如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达项层的启动类加载器;
3、如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务(有的加载器只能加载特定的类,如Java核心库类),子加载器才会尝试自己去加载,这就是双亲委派模式。

优点:

  • 避免类被重复加载
  • 保护程序安全,防止API被篡改(沙箱安全机制)
    java.lang.SecurityException: Prohibited package name: java.lang

在JVM中表示两个class对象是否为同一个类存在两个必要条件:
1、类的完整类名必须一致,包括包名。
2、加载这个类的ClassLoader (指ClassLoader实例对象)必须相同。.

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值