jvm 类的加载机制

前言

类加载机制:将一个类的.class文件的二进制字节流数据,读取到内存中,并且创建一个java.lang.Class对象,封装到元数据空间的数据存储结构

1. Class Loader分类

1.1 Bootstrap ClassLoader(根加载器)

a.加载 $JAVA_HOME jre/lib/rt.jar 里所有的 class Xbootclasspath 选项指定的 jar
b.不继承ClassLoader
c.并非java实现,而是C++实现

1.2 Extension ClassLoader(扩展类加载器)

加载 java 平台中扩展功能的一些 jar 包,包括 $JAVA_HOME jre/lib/ext/*.jar -Djava.ext.dirs(启动指令属性)指定目录下的 jar 包,比如 C:\Program Files\Java\jdk1.8.0_152\jre\lib下的所有 jar 包的类
具体实现为 sum.misc.Launcher 中的内部类 ExtClassLoader

1.3 Application ClassLoader(系统类加载器)

我们平时写的代码都是由系统类加载器加载

具体实现为 sum.misc.Launcher 中的内部类 AppClassLoader

1.4 自定义类加载器

继承ClassLoader

2.双亲委派机制

由来:

默认的情况下,一个限定名的类只会被一个类加载器加载解析并使用,这样在程序 中,它就是唯一的,不会产生歧义。由此出现双亲委派机制保证类加载的唯一性

a.当一个类加载器收到类加载请求时,它不会先自己去加载,而是交由父类加载器去加载,传递到最上层的Bootstrap ClassLoader加载器无法加载该类时,再传递给子类加载器加载。

b.无法加载:类加载根据类的全限定名,在类负责的加载路径中找不到该类

c.上图中箭头指向并非继承关系,而是一种组合方式实现的逻辑关系

d.双亲委派的代码实现

 

 双亲委派目的:为了保证核心类库的安全、防止篡改、保证类的唯一性

3.如何打破双亲委派机制

1.重写loadClass方法

问题:既然jvm推荐并且希望开发者遵循双亲委派机制,为什么不把loadClass方法设置为final方法,这样就可以有效防止重写loadClass方法

回答:双亲委派机制是jdk1.2提出的,但是java.lang.ClassLoader load class方法呢在java很早的版本就有了。引出双亲委派机制时,已经有很多重写loadClass这样的方法了,所有jvm只能采取向下兼容的方式。推荐用户去重写findClass()方法,而不是重写loadClass()方法。

2.SPI打破双亲委派机制

举例 

jdk需要提供数据库的功能,但是只是提供了Driver接口,具体实现由数据库产商自己去实现。而jdk代码包中的代码是由BootStrap类加载器去加载,这时候如果由BootStrap类加载器去加载接口实现类,就会导致上层类加载器调用下层类加载器的情况,产生了双亲委派模型的破坏。

所以java为了解决这个问题提出了SPI机制,将META-INF/services/下文件的类委派给子类加载器去加载到JVM中

在DriverManager 类静态代码块中调用了loadInitialDrivers()方法

 调用ServiceLoader.load(Driver.class)方法,由子类加载器加载META-INF/services/java.sql.Driver 文件里边的类到JVM内存

 查看类加载器情况

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值