jvm类加载器,类加载机制详解,看这一篇就够了

前言

今天我们来讲讲jvm类加载的过程,我们写了那么多类,却不知道类的加载过程,岂不是很尴尬

jvm的启动是通过引导类加载器(bootstrap class loader)创建一个初始类(initial class)来完成的,这个类是由jvm的具体实现指定的。[来自官方规范]

jvm组成结构之一就是类装载器子系统,我们今天就来仔细讲讲这个组件。

Java代码执行流程图

大家通过这个流程图,了解一下我们写好的Java代码是如何执行的,其中要经历类加载器这个流程,我们就来仔细讲讲这里面的知识点。

jvm类加载器,类加载机制详解,看这一篇就够了

类加载子系统

jvm类加载器,类加载机制详解,看这一篇就够了

类加载系统架构图

暂时看不懂这两张图没关系,跟着老哥往下看

jvm类加载器,类加载机制详解,看这一篇就够了

类的生命周期

类的生命周期包括:加载、链接、初始化、使用和卸载,其中加载链接初始化,属于类加载的过程,我们下面仔细讲解。使用是指我们new对象进行使用,卸载指对象被垃圾回收掉了。

类加载的过程

jvm类加载器,类加载机制详解,看这一篇就够了

  • 第一步:Loading加载

总结:加载二进制数据到内存 —> 映射成jvm能识别的结构 —> 在内存中生成class文件

  • 第二步:Linking链接

链接是指将上面创建好的class类合并至Java虚拟机中,使之能够执行的过程,可分为验证准备解析三个阶段。

① 验证(Verify)

② 准备(Prepare)

③ 解析(Resolve)

  • 第三步:initialization初始化

类加载器的分类

jvm类加载器,类加载机制详解,看这一篇就够了

  • 第一个:启动类/引导类:Bootstrap ClassLoader

  • 第二个:扩展类加载器:Extension ClassLoader

  • 第三个:应用程序类加载器:Application Classloader

  • 第四个:自定义加载器

自定义加载器实现步骤

获取ClassLoader几种方式

它是一个抽象类,其后所有的类加载器继承自 ClassLoader(不包括启动类加载器)

// 方式一:获取当前类的 ClassLoader

clazz.getClassLoader()

// 方式二:获取当前线程上下文的 ClassLoader

Thread.currentThread().getContextClassLoader()

// 方式三:获取系统的 ClassLoader

ClassLoader.getSystemClassLoader()

// 方式四:获取调用者的 ClassLoader

DriverManager.getCallerClassLoader()

类加载机制—双亲委派机制

jvm对class文件采用的是按需加载的方式,当需要使用该类时,jvm才会将它的class文件加载到内存中产生class对象。

在加载类的时候,是采用的双亲委派机制,即把请求交给父类处理的一种任务委派模式。

jvm类加载器,类加载机制详解,看这一篇就够了

  • 工作原理

(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类加载器变得更加灵活。

jvm类加载器,类加载机制详解,看这一篇就够了

  • 沙箱安全机制

自定义 String 类,但是在加载自定义 String 类的时候会率先使用引导类加载器加载,而引导类加载器在加载的过程中会先加载 JDK 自带的文件(rt.jar 包中的 javalangString.class),报错信息说没有 main 方法就是因为加载的 rt.jar 包中的 String 类。这样可以保证对 Java 核心源代码的保护,这就是沙箱安全机制。

IT 老哥

我是一个通过大学四年自学,进入大厂做高级java开

发的程序员。关注我,每天分享技术干货,助你进大

厂。我可以,你也可以的。

如果你觉得文章写的还不错,请帮老哥点个赞!

以上是 jvm类加载器,类加载机制详解,看这一篇就够了 的全部内容, 来源链接: utcz.com/a/62932.html

回到顶部