「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。
前言
小伙伴们我回来更文啦,其实是临近过年空出时间了,哈哈。
看了上面的标题,有没有小伙伴觉得类加载和我们其实很遥远,完全不需要关注,赞同的举个爪。
但仔细回想下,其实你时时刻刻都在和它发生交集,比如:基于动态代理的注解(@Transactional
),开发必备的热加载工具:jrebal
,排查工具:arthas
等。这些足以证明它很重要。
这个专栏的文章灵感来源于自己想造个类似于SpringBootDevTool
的轮子。如果你想了解类加载,但又对它很陌生,不知道它怎么实现的。别慌,这个Jvm
系列会帮你讲明白。
类加载步骤
整体的类加载分为以下七个步骤
- 加载
- 验证
- 准备
- 解析
- 初始化
- 使用
- 卸载
在这七个步骤中,当然主要关注的只有3个。当然由于篇幅原因,本文主要内容是加载(加载都讲不完!)
什么是类加载
- 在创建一个类后,JVM编译器会将
.java
文件编译成.Class
字节码文件。 - 然后在JVM启动时,会把描述类的数据从
.Class
文件(非必须)加载到内存,并对数据进行校验、转换解析和初始化。 - 最终形成可以被JVM直接使用的Java类型,放在JVM的各块内存区域中。
字节码来源
上文写了Class
文件加载到内存,那有没有其他形式呢?往下看!
- 从ZIP包中读取。 例子: jar包
- 从网络中获取。 参考: UrlClassLoader(接下来的jvm系列会讲)
- 运行时计算生成。 动态代理技术:AOP
- 由其他文件生成。 例子:Jsp文件
- 从数据库中读取。 我也没试过..
类加载器
既然需要加载类,那我们自然需要某种工具。在JVM中,这就是大名鼎鼎的类加载器了。
在我们的代码设计中,有着低耦合和高内聚的设计原则。在类加载器中,为了将职责区分开,并且保证JDK
基本代码和项目中的业务代码区分开等各种原因,JVM
定义了不同的类加载器:BootstrapClassLoader
,ExtensionClassLoader
,AppClassLoader
。它们各自都有着自己的加载路径和加载时机。
Bootstrap ClassLoader
- 加载路径:lib/rt.jar等类
- 加载时机:jvm启动时
在启动jvm时添加该命令, -XX:+TraceClassLoading,就能看到加载的类啦。有没有发现下图的类很熟悉
Extension ClassLoader
- 加载路径:jre/lib/ext, 如果用户自定义Jar包也在该路径,同样会被加载
- 加载时机:jvm启动时
App ClassLoader
- 加载路径:应用程序当前路径
- 加载时机:系统启动时需要加载的类,例如:SpringBoot下Controller。或者项目运行时加载的类
自定义 ClassLoader
- 加载路径:类加载器设置的地方
- 加载时机:手动触发
结尾
这篇文章到这里就结束了。本文介绍了什么是类加载,同时粗略的讲了类加载的工具->类加载器。下篇将会着重介绍JVM
是如何巧妙使用这些类加载器,也就是双亲委派模型的实现。
喜欢这篇文章的话点个赞哦,咱们下期见!!