首页 > 其他分享 >JVM(二)-- 类加载机制

JVM(二)-- 类加载机制

时间:2022-11-29 23:22:29浏览次数:59  
标签:委派 loadClass -- ClassLoader 双亲 JVM 重写 加载

类加载机制

官网:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html

Loading

ClassLoader

双亲委派机制

(1)检查某个类是否已经加载

自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个Classloader已加载,就视为已加载此类,保证此类只所有ClassLoader加载一次。

(2)加载的顺序

自顶向下,也就是由上层来逐层尝试加载此类。

代码示例
public static void main(String[] args) {

    //AppClassLoader
    System.out.println(new User().getClass().getClassLoader());

    //ExtClassLoader
    System.out.println(new User().getClass().getClassLoader().getParent());

    //Bootstrap ClassLoader   是c++写的 所以这里打印出来为null
    System.out.println(new User().getClass().getClassLoader().getParent().getParent());

    //这里也为null  String是在Bootstrap ClassLoader中加载的
    System.out.println(new String().getClass().getClassLoader());
}
破坏双亲委派

(1)第一次破坏

在 jdk 1.2 之前,那时候还没有双亲委派模型,不过已经有了 ClassLoader 这个抽象类,所以已经有人继承这个抽象类,重写 loadClass 方法来实现用户自定义类加载器。

而在 1.2 的时候要引入双亲委派模型,为了向前兼容, loadClass 这个方法还得保留着使之得以重写,新搞了个 findClass 方法让用户去重写,并呼吁大家不要重写 loadClass 只要重写 findClass。

这就是第一次对双亲委派模型的破坏,因为双亲委派的逻辑在 loadClass 上,但是又允许重写 loadClass,重写了之后就可以破坏委派逻辑了

(2)tomcat

Tomcat就是用这种方式对双亲委派进行破坏,来达到使用一个web容器部署两个或者多个应用程序,不同的应用程序,可能依赖同一个第三方类库的不同版本,还要保证每一个应用程序的类库都是独立、相互隔离的效果。

tomcat自定义类加载器,重写loadClass方法使其优先加载自己目录下的class文件,来达到class私有的效果。

(3)基于SPI

例如:JNDI服务

它的代码是启动类加载器去加载的,JNDI的目的是为了对资源进行集中管理与查找,它需要调用由独立厂商实现并部署在应用程序的ClassPath下的JNDI接口提供者的代码,但启动类加载器显然不会知道这些代码。

由此,Java的设计团队引入了一个不怎么优雅的设计:线程上下文类加载器;这个类加载器可以通过java.lang.Thread类的setContextClassLoader()方法进行设置,在创建线程时如果还未设置的话,
他会从父线程中继承一个,如果在应用程序的全局范围内都没有设置过的话,那么这个类加载器默认就是应用程序类加载器。

这样,JNDI服务就可以去加载它所需要的SPI代码,但这种打通了双亲委派模型层次结构由此来逆向使用类加载器的行为,实际上就已经违背了双亲委派模型的一般性原则!

(4) OSGI (开放服务网关协议,Open Service Gateway Initiative)

 OSGI 就是利用自定义的类加载器机制来完成模块化热部署,而它实现的类加载机制就没有完全遵循自下而上的委托,有很多平级之间的类加载器查找。

(5)第五次破坏

在 JDK9 引入模块系统之后,类加载器的实现其实做了一波更新。

像扩展类加载器被重命名为平台类加载器,核心类加载归属了做了一些划分,平台类加载器承担了更多的类加载,上面提到的 -Xbootclasspath、java.ext.dirs 也都无效了,rt.jar 之类的也被移除,
被整理存储在 jimage 文件中,通过新的 JRT 文件系统访问。

当收到类加载请求,会先判断该类在具名模块中是否有定义,如果有定义就自己加载了,没的话再委派给父类。
双亲委派被破坏的补救措施

java.lang.ClassLoader的loadClass方法在Java很早的版本就有了,而双亲委派模型是在JDK1.2中引入的。java是向下兼容的,所以不是不想改而是改不了。一个补救措施是使用findClass方法而不是直接重写loadClass。

Linking

Verification

保证被加载类的正确性

Preparation

为类的静态变量分配内存,并将其初始化为默认值

Resolution

把类中的符号引用转换为直接引用

Initialization

对类的静态变量,静态代码块执行初始化操作

标签:委派,loadClass,--,ClassLoader,双亲,JVM,重写,加载
From: https://www.cnblogs.com/snail-gao/p/16937082.html

相关文章

  • bat脚本查找指定目录下的文件并将所有文件内容合并输出到一个文件里 写软著专用提取代
    1.将下面的代码复制到 并另存为【查找文件并合并内容.bat】里echooff&color0A::判断输入路径是不是文件夹,如果是,则获取文件夹下的所有文件名(包括子文件夹下的):......
  • 离散数学左孝凌-图论1
    图的基本概念路与回路......
  • 华为 EulerOS ffmpeg 编译安装
    官网:https://ffmpeg.org各个版本自行选择:https://ffmpeg.org/releases/安装环境  https://ffmpeg.org/releases/从这里找到最新版本的源码,进行下载cd/opt/app/wge......
  • python 对接各大数据库,快速上手!
     1、mysql  安装pymysqlpipintsallpymysql快速上手importpymysql#第一步:连接到数据库con=pymysql.connect(host="xxxx",#数据库......
  • 迭代器模式
    1. 迭代器模式简介     把对容器中包含的内部对象的访问委让给外部类,使用Iterator(遍历)按顺序进行遍历访问的设计模式。   如果不使用Iterator模式,会......
  • 集合
    集合集合概述数组其实就是一个集合。集合实际上就是一个容器。可以来容纳其它类型的数据。集合为什么说在开发中使用较多?集合是一个容器,是一个载体,可以一次容纳多个对......
  • Python基本语法
    Python基本语法字面量掌握字面量的含义代码中,被写在代码中的固定的值,称之为字面量常见的字面量类型我们目前了解:整数、浮点数、字符串这三类即可基于print语句完成......
  • 数组
    数组常见操作遍历,指的就是“通过循环遍历数组的所有元素”。拷贝,指的是将某个数组的内容拷贝到另一个数组中。注:实质上,后面大家学容器的扩容就是“数组的拷贝”。......
  • 练习_(if、case)多系统配置yum源
    #!/usr/bash/binyum_server=192.168.201.130os_version=`cat/etc/redhat-release|awk'{print$4}'|awk-F"."'{print$1"."$2}'`[-d/etc/yum.repos.d]||mk......
  • 垃圾回收机制
    什么是垃圾回收机制:  垃圾回收机制是js内置的一种管理机制它会自动分配内存和自动回收不再使用的内存  垃圾回收机制的两种算法:引用计数法标记清除法  ......