JDK 9 的 PlatformClassLoader 只是简单改个名吗?
都知道JDK9之后将扩展类加载器(ExtensionClassLoader)重命名为平台类加载器(PlatformClassLoader),难道只是简单的重命名吗?都有什么变化?
带来的变化
1.双亲委派模型的改变
JDK8:双亲委派是严格的“向上查找”:自定义——>App——>Ext——>Boot
JDK9+:为了适配模块化,当类加载器收到加载请求时,会先判断该类是否属于某个具体的模块
如果该类已经归属于某个模块,Java 会直接将请求委派给负责该模块的类加载器,而不再一层层往上托举

什么?谁判断的该类是否属于某个具体的模块?is引入的BuiltinClassLoader判断的
package jdk.internal.loader;
protected Class<?> loadClassOrNull(String cn, boolean resolve) {
synchronized (getClassLoadingLock(cn)) {
// 检查这个类是否已经被加载过
Class<?> c = findLoadedClass(cn);
if (c == null) {
// 查找它属于哪个模块
LoadedModule loadedModule = findLoadedModule(cn);
// --------- 情况 A:属于某个模块(走直达) -----------
//查到了,属于某个模块
if (loadedModule != null) {
//获取这个模块的类加载器
BuiltinClassLoader loader = loadedModule.loader();
//如果是我自己
if (loader == this) {
//模块系统初始化完成后,由我自己去加载
if (VM.isModuleSystemInited()) {
c = findClassInModuleOrNull(loadedModule, cn);
}
} else {
//甩给对应的加载器,实现“直达”
c = loader.loadClassOrNull(cn);
}
} else {
//--------- 情况 B:不属于任何已知模块(走传统双亲委派) -----------
//向上委派
if (parent != null) {
c = parent.loadClassOrNull(cn);
}
// 向下退回
if (c == null && hasClassPath() && VM.isModuleSystemInited()) {
c = findClassOnClassPathOrNull(cn);
}
}
}
if (resolve && c != null)
resolveClass(c);
return c;
}
}
什么是模块化?
JDK9之前,只有包和Jar包,
问题一:只要一个jar包在ClassPath里,它里面所有的public类都能被任意访问,但我的public只想当前组件内部用,不暴露给外部
问题二:如果运行时两个jar包里有同名同包的类,先扫描的会覆盖后面的,会报错(如 NoSuchMethodError)。
模块化系统,在包之上加了层:模块
一个模块不仅包含代码,还包含核心描述文件module-info.java:
- 我导出了什么(exports): 只有被导出的包,别的模块才能访问。
- 我依赖了什么(requires): 明确声明我需要哪些模块才能运行。
2.启动类加载器的改变
脱离了 C++ 的“隐形”实现: 在过去,Bootstrap ClassLoader 完全由 C++ 实现,在 JDK 9 之后引入了BuiltinClassLoader 的 Java 类。现在,Bootstrap、Platform 和 App 加载器全都继承自 BuiltinClassLoader。
不再加载所有核心库: 过去所有的 Java 核心类都由 Bootstrap 一把抓。现在,核心类被拆分成了不同的模块,Bootstrap 只负责加载最核心的模块(如 java.base),而 java.sql(数据库相关)、java.xml 等模块,则交给了平台类加载器去加载。
3.目录结构与打包文件消失
rt.jar 和 tools.jar 消失了,所有内置类被重新打包成模块,存在了lib/modules
4.类加载器微调
内置的三个加载器都改为了 BuiltinClassLoader 的子类
好处:
- 运行时性能与启动速度的飞跃,省去了沿途无效的逐级托举和全盘文件扫描
- 强封装性,阻止访问核心库内部的私有实现,
- 配置更可靠,项目依赖A.jar A.jar依赖B.jar,运行时不报错,但是执行A.jar里的某行代码,要加载B.jar里的类时,就会抛
ClassNotFoundException或NoClassDefFoundError现在: 模块化要求在module-info.java中明确声明requires哪些模块。
package java.lang.module;
public Builder requires(Requires req) {
if (automatic)
throw new IllegalStateException("Automatic modules cannot declare"
+ " dependences");
String mn = req.name();
if (name.equals(mn))
throw new IllegalArgumentException("Dependence on self");
if (requires.containsKey(mn))
throw new IllegalStateException("Dependence upon " + mn
+ " already declared");
requires.put(mn, req);
return this;
}
- jlink自动裁剪,用什么裁什么
更多推荐




所有评论(0)