jvm类加载器,类加载机制详解,看这一篇就够了
前言
今天我们来讲讲jvm
里类加载
的过程,我们写了那么多类,却不知道类的加载过程,岂不是很尴尬
。
jvm
的启动是通过引导类加载器(bootstrap class loader)创建一个初始类(initial class)来完成的,这个类是由jvm
的具体实现指定的。[来自官方规范]
jvm组成结构之一就是类装载器子系统
,我们今天就来仔细讲讲这个组件。
Java代码执行流程图
大家通过这个流程图,了解一下我们写好的Java代码是如何执行的,其中要经历类加载器
这个流程,我们就来仔细讲讲这里面的知识点。
类加载子系统
类加载系统架构图
暂时看不懂这两张图没关系,跟着老哥
往下看
类的生命周期
类的生命周期包括:加载、链接、初始化、使用和卸载,其中加载
、链接
、初始化
,属于类加载的过程
,我们下面仔细讲解。使用是指我们new对象进行使用,卸载指对象被垃圾回收掉了。
类加载的过程
- 第一步:Loading加载
总结:加载二进制数据到内存
—> 映射成jvm能识别的结构
—> 在内存中生成class文件
。
- 第二步:Linking链接
链接是指将上面创建好的class类合并至Java虚拟机中,使之能够执行的过程,可分为验证
、准备
、解析
三个阶段。
① 验证(Verify)
② 准备(Prepare)
③ 解析(Resolve)
- 第三步:initialization初始化
类加载器的分类
- 第一个:启动类/引导类:Bootstrap ClassLoader
- 第二个:扩展类加载器:Extension ClassLoader
- 第三个:应用程序类加载器:Application Classloader
- 第四个:自定义加载器
自定义加载器实现步骤
获取ClassLoader几种方式
它是一个抽象类,其后所有的类加载器继承自 ClassLoader(不包括启动类加载器)
// 方式一:获取当前类的 ClassLoaderclazz.getClassLoader()
// 方式二:获取当前线程上下文的 ClassLoader
Thread.currentThread().getContextClassLoader()
// 方式三:获取系统的 ClassLoader
ClassLoader.getSystemClassLoader()
// 方式四:获取调用者的 ClassLoader
DriverManager.getCallerClassLoader()
类加载机制—双亲委派机制
jvm对class文件采用的是按需加载的方式,当需要使用该类时,jvm才会将它的class文件加载到内存中产生class对象。
在加载类的时候,是采用的双亲委派机制
,即把请求交给父类处理的一种任务委派模式。
- 工作原理
(1)如果一个类加载器
接收到了类加载
的请求,它自己不会先去加载,会把这个请求委托给父类加载器
去执行。
(2)如果父类还存在父类加载器,则继续向上委托,一直委托到启动类加载器:Bootstrap ClassLoader
(3)如果父类加载器可以完成加载任务,就返回成功结果,如果父类加载失败,就由子类自己去尝试加载,如果子类加载失败就会抛出ClassNotFoundException
异常,这就是双亲委派模式
- 第三方包加载方式:反向委派机制
在Java应用中存在着很多服务提供者接口(Service Provider Interface,SPI),这些接口允许第三方为它们提供实现,如常见的 SPI 有 JDBC、JNDI等,这些 SPI 的接口属于 Java 核心库,一般存在rt.jar包中,由Bootstrap类加载器加载。而Bootstrap类加载器无法直接加载SPI的实现类,同时由于双亲委派模式的存在,Bootstrap类加载器也无法反向委托AppClassLoader加载器SPI的实现类。在这种情况下,我们就需要一种特殊的类加载器来加载第三方的类库,而线程上下文类加载器(双亲委派模型的破坏者)就是很好的选择。
从图可知rt.jar核心包是有Bootstrap类加载器加载的,其内包含SPI核心接口类,由于SPI中的类经常需要调用外部实现类的方法,而jdbc.jar包含外部实现类(jdbc.jar存在于classpath路径)无法通过Bootstrap类加载器加载,因此只能委派线程上下文类加载器把jdbc.jar中的实现类加载到内存以便SPI相关类使用。显然这种线程上下文类加载器的加载方式破坏了“双亲委派模型”,它在执行过程中抛弃双亲委派加载链模式,使程序可以逆向使用类加载器,当然这也使得Java类加载器变得更加灵活。
- 沙箱安全机制
自定义 String 类,但是在加载自定义 String 类的时候会率先使用引导类加载器加载,而引导类加载器在加载的过程中会先加载 JDK 自带的文件(rt.jar 包中的 javalangString.class),报错信息说没有 main 方法就是因为加载的 rt.jar 包中的 String 类。这样可以保证对 Java 核心源代码的保护,这就是沙箱安全机制。
IT 老哥
我是一个通过大学四年自学,进入大厂做高级java开
发的程序员。关注我,每天分享技术干货,助你进大
厂。我可以,你也可以的。
如果你觉得文章写的还不错,请帮老哥点个赞!
以上是 jvm类加载器,类加载机制详解,看这一篇就够了 的全部内容, 来源链接: utcz.com/a/62932.html