惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Darknet – Hacking Tools, Hacker News & Cyber Security
V
Vulnerabilities – Threatpost
Cloudbric
Cloudbric
G
GRAHAM CLULEY
S
Securelist
Schneier on Security
Schneier on Security
Help Net Security
Help Net Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Project Zero
Project Zero
Spread Privacy
Spread Privacy
P
Privacy International News Feed
C
Cyber Attacks, Cyber Crime and Cyber Security
Cisco Talos Blog
Cisco Talos Blog
T
Tailwind CSS Blog
博客园_首页
有赞技术团队
有赞技术团队
Simon Willison's Weblog
Simon Willison's Weblog
Stack Overflow Blog
Stack Overflow Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Latest news
Latest news
T
Tor Project blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Attack and Defense Labs
Attack and Defense Labs
www.infosecurity-magazine.com
www.infosecurity-magazine.com
O
OpenAI News
J
Java Code Geeks
T
Tenable Blog
K
Kaspersky official blog
AWS News Blog
AWS News Blog
S
Security @ Cisco Blogs
The GitHub Blog
The GitHub Blog
T
Threatpost
月光博客
月光博客
H
Heimdal Security Blog
Security Latest
Security Latest
The Hacker News
The Hacker News
Y
Y Combinator Blog
A
Arctic Wolf
Apple Machine Learning Research
Apple Machine Learning Research
C
Cisco Blogs
美团技术团队
Microsoft Security Blog
Microsoft Security Blog
Hugging Face - Blog
Hugging Face - Blog
T
The Blog of Author Tim Ferriss
C
CERT Recently Published Vulnerability Notes
D
Docker
Google Online Security Blog
Google Online Security Blog
D
DataBreaches.Net
V
Visual Studio Blog
H
Help Net Security

博客园 - BigOrang

在vim中搜索关键字 linux top快捷键 druid 获取数据库连接失败,一直wait.DruidDataSource.takeLast -Xmx3G -Xms2G 在已经指定了最小内存2G后,启动的时候,就会直接分配2G给jvm吗 ?还是动态从1m到2G逐步分配的 windows查看端口占用 vmware Docker 设置代理 腾讯云域名托管到 cloudflare nginx 代理eureka后css/js/fonts无法访问 docker 基础镜像损坏 一起来找bug茬-01 mysql SHOW PROFILE 将所有容器docker都重启, 但是不重启mysql 正则 .*? 和 .* 的区别是什么 nginx打印所有配置内容 NoClassDefFoundError: org/slf4j/impl/StaticLoggerBinder kubesphere org.tmatesoft.svn.core.SVNException: svn: E160013: '/leifengyang/yygh-parent.git' path not found: 404 Not Found (https://gitee.com) 布隆过滤器原理及应用场景 linux中,使用alias, 应该在/etc/bashrc 中写,还是~/.bashrc中写,哪个更好 java date 时间最大连续天数
java8类加载器示例&类加载1.8和1.8+的区别
BigOrang · 2025-04-19 · via 博客园 - BigOrang

示例代码

package com.example.demo;

public class ClassLoaderExample {
    public static void main(String[] args) {
        // 1.8及以下ClassLoaderExample sun.misc.Launcher$AppClassLoader@18b4aac2
        // 1.9+ ClassLoaderExample jdk.internal.loader.ClassLoaders$AppClassLoader@63947c6b
        System.out.println("ClassLoaderExample " + ClassLoaderExample.class.getClassLoader());

        // 1.8及以下:ClassLoaderExample getParent sun.misc.Launcher$ExtClassLoader@4c873330
        // jdk9+ ClassLoaderExample getParent jdk.internal.loader.ClassLoaders$PlatformClassLoader@26a1ab54
        System.out.println("ClassLoaderExample getParent " + ClassLoaderExample.class.getClassLoader().getParent());

        // 1.8及以下 ClassLoaderExample getParent null 
        // jdk9+  ClassLoaderExample getParent getParent null
        System.out.println("ClassLoaderExample getParent getParent " + ClassLoaderExample.class.getClassLoader().getParent().getParent());

        // 1.8及以下 null
        // jdk9+ null
        System.out.println("String " + String.class.getClassLoader());

        // 1.8及以下 Exception in thread "main" java.lang.NullPointerException
        // jdk9+ Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.ClassLoader.getParent()" because the return value of "java.lang.Class.getClassLoader()" is null     at 
        // com.example.demo.ClassLoaderExample.main(ClassLoaderExample.java:18)
        System.out.println("String getParent " + String.class.getClassLoader().getParent());
    }
}

🌳 类加载器(ClassLoader)结构回顾

Java 的类加载器是分层级的,主要有三种类加载器(JDK 8 及以前):

  1. Bootstrap ClassLoader(引导类加载器)
    • 加载 Java 核心类库,如 java.lang.*
    • 用 C++ 编写,是 JVM 内部的一部分。
    • 不是 Java 对象(即不是 ClassLoader 的子类实例),因此在 Java 层获取不到它的引用(表现为 null)。
  2. Extension ClassLoader(扩展类加载器)
    • 加载 jre/lib/ext/ 目录下的类。
    • 是 Java 编写的,sun.misc.Launcher$ExtClassLoader 实例。
  3. Application ClassLoader(应用类加载器)
    • 加载应用程序 classpath 下的类。
    • 也是 Java 编写的,sun.misc.Launcher$AppClassLoader 实例。

代码运行时打印信息解释

System.out.println("ClassLoaderExample " + ClassLoaderExample.class.getClassLoader());

输出类似于:

ClassLoaderExample sun.misc.Launcher$AppClassLoader@18b4aac2

说明当前类是由应用类加载器加载的。


System.out.println("ClassLoaderExample getParent " + ClassLoaderExample.class.getClassLoader().getParent());

输出:

ClassLoaderExample getParent sun.misc.Launcher$ExtClassLoader@4c873330

AppClassLoader 的父类是 ExtClassLoader,正确无误。


System.out.println("ClassLoaderExample getParent getParent " + ClassLoaderExample.class.getClassLoader().getParent().getParent());

输出:

ClassLoaderExample getParent getParent null

✅ 解释:为什么最后是 null

  • ExtClassLoader 的父类是 Bootstrap ClassLoader
  • 但是 Bootstrap ClassLoader 是 JVM 内部实现,不是一个 Java 对象
  • 在 Java 层调用 getParent() 时,如果父加载器是 Bootstrap,就会返回 null

👉 换句话说:

ExtClassLoader.getParent() = BootstrapClassLoader → null in Java

所以你看到的是:

AppClassLoader.getParent()           = ExtClassLoader
ExtClassLoader.getParent()          = BootstrapClassLoader → null

✅ 小结

类加载器 类名 getParent() 的结果
应用类加载器 sun.misc.Launcher$AppClassLoader 返回 ExtClassLoader
扩展类加载器 sun.misc.Launcher$ExtClassLoader 返回 null(实际是 Bootstrap)
引导类加载器 JVM 内部实现(非 Java 对象) 无法用 Java 代码直接引用,getParent 为 null

好的,我们来系统性、严谨地讲解一下 Java 9 模块系统(Project Jigsaw) 引入之后,类加载器机制的变化 —— 特别是与模块(module)系统结合之后的差异。


🔧 Java 9 模块系统与类加载器关系变更详解

一、背景:Project Jigsaw(Java 9 引入)

Java 9 引入了 模块系统(Module System),目的是:

  • 增强封装性和可维护性。
  • 将 JDK 自身模块化(比如 java.base, java.sql, java.xml 等)。
  • 支持用户定义模块(module-info.java)。

二、Java 9 之前的类加载器结构(复习)

我们回顾下 JDK 8 及以前的类加载器结构:

BootstrapClassLoader  (C++实现,加载核心类库)
        ↑
ExtClassLoader        (Java实现,加载jre/lib/ext下类库)
        ↑
AppClassLoader        (Java实现,加载classpath中的类)

三、Java 9 之后:类加载器结构变化

主要变化:

  1. 引入了 Platform ClassLoader(新的中间层)。
  2. 扩展类加载器 ExtClassLoader 被废弃。
  3. 新的加载器层级结构如下:
BootstrapClassLoader      -> 加载 java.base 等核心模块
        ↑
PlatformClassLoader       -> 加载 JDK 提供的其他模块(例如 java.sql)
        ↑
AppClassLoader            -> 加载用户模块(即 classpath 或 modulepath 中的应用模块)

📌 说明:

  • PlatformClassLoader 替代了原来的 ExtClassLoader
  • 它加载的是 JDK 提供的标准模块,而不是 jre/lib/ext 目录(该目录从 Java 9 开始被废弃)。

四、PlatformClassLoader 特点

你可以通过以下方式访问:

ClassLoader platformClassLoader = ClassLoader.getPlatformClassLoader();

并通过查看其层级:

System.out.println("PlatformClassLoader: " + platformClassLoader);
System.out.println("PlatformClassLoader parent: " + platformClassLoader.getParent());

它的父类仍然是 BootstrapClassLoader(Java 中表现为 null)。


五、类与类加载器的关系在模块系统中的影响

模块系统不仅组织代码包,还与类加载器紧密相关:

模块位置 类加载器
java.base 等核心模块 BootstrapClassLoader
java.sql 等平台模块 PlatformClassLoader
用户定义模块 AppClassLoader

举个例子:

System.out.println("String.class loader: " + String.class.getClassLoader()); // null(Bootstrap)
System.out.println("java.sql.Driver.class loader: " + java.sql.Driver.class.getClassLoader()); // PlatformClassLoader
System.out.println("你自己的类 loader: " + YourClass.class.getClassLoader()); // AppClassLoader

六、模块系统对反射和访问权限的限制

Java 9 引入模块系统后,对于 setAccessible(true) 等反射操作增加了限制,默认情况下不能访问其它模块中未开放的 package

你需要:

  • 在命令行中添加 --add-opens 参数;
  • 或在模块描述符中添加 opensexports

✅ 总结

Java 版本 类加载器结构变化说明
Java 8及以前 Bootstrap → Ext → App
Java 9及以后 Bootstrap → Platform → App(Ext废弃)

主要新增:

  • PlatformClassLoader:加载平台模块,替代原 ExtClassLoader
  • 模块系统与类加载器绑定更紧密,强调包封装与访问控制。