JAVA类加载原理解析

1、JVM预定义加载器
(1) 启动(Bootstrap)类加载器:引导类装入器是用本地代码实现的类装入器。加载 <Java_Runtime_Home>/lib下面的核心类库或-Xbootclasspath选项指定的jar包加载到内存中。
(2) 扩展(Extension)类加载器:扩展类加载器是由Sun的ExtClassLoader(sun.misc.Launcher E x t C l a s s L o a d e r ) 实 现 的 。 它 负 责 将 &lt; J a v a R u n t i m e H o m e &gt; / l i b / e x t 或 者 由 系 统 变 量 − D j a v a . e x t . d i r 指 定 位 置 中 的 类 库 加 载 到 内 存 中 。 ( 3 ) 系 统 ( S y s t e m ) 类 加 载 器 : 系 统 类 加 载 器 是 由 S u n 的 A p p C l a s s L o a d e r ( s u n . m i s c . L a u n c h e r ExtClassLoader)实现的。它负责将&lt; Java_Runtime_Home &gt;/lib/ext或者由系统变量-Djava.ext.dir指定位置中的类库加载到内存中。 (3) 系统(System)类加载器:系统类加载器是由 Sun的 AppClassLoader(sun.misc.Launcher ExtClassLoader<JavaRuntimeHome>/lib/extDjava.ext.dir(3)SystemSunAppClassLoadersun.misc.LauncherAppClassLoader)实现的。它负责将系统类路径java -classpath或-Djava.class.path变量所指的目录下的类库加载到内存中。
2、双亲委派模型
(1) 在JVM类加载中,使用的是双亲委派模型,就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
(2) 类加载器间的相互关系
在这里插入图片描述
3、自定义加载器的工作流程
(1) 首先检查请求的类型是否已经被这个类装载器装载到命名空间中了,如果已经装载,直接返回;否则转入步骤2;
(2) 派类加载请求给父类加载器(更准确的说应该是双亲类加载器,真实虚拟机中各种类加载器最终会呈现树状结构),如果父类加载器能够完成,则返回父类加载器加载的Class实例;否则转入步骤3;
(3) 调用本类加载器的findClass(…)方法,试图获取对应的字节码,如果获取的到,则调用defineClass(…)导入类型到方法区;如果获取不到对应的字节码或者其他原因失败,返回异常给loadClass(…), loadClass(…)转而抛异常,终止加载过程
在这里插入图片描述
4、类加载器原理说明
(1)在JVM中不同类加载器加载同一个类得到的实例不相同,JVM中一个类用其全名和一个加载类ClassLoader的实例作为唯一标识,不同类加载器加载的类将被置于不同的命名空间。
(2)在Java虚拟机判断两个类是否相同的时候,使用的是类的定义加载器。也就是说,哪个类加载器启动类的加载过程并不重要,重要的是最终定义这个类的加载器。两种类加载器的关联之处在于:一个类的定义加载器是它引用的其它类的初始加载器。
(3)方法 loadClass()抛出的是 java.lang.ClassNotFoundException异常;方法 defineClass()抛出的是 java.lang.NoClassDefFoundError异常。
(4)类加载器在成功加载某个类之后,会把得到的 java.lang.Class类的实例缓存起来。下次再请求加载该类的时候,类加载器会直接使用缓存的类的实例,而不会尝试再次加载。也就是说,对于一个类加载器实例来说,相同全名的类只加载一次,即 loadClass方法不会被重复调用。
5、线程上下文加载器
我们可以通过java.lang.Thread类中的getContextClassLoader()和 setContextClassLoader(ClassLoader cl)方法来获取和设置线程的上下文类加载器。初始线程的上下文类加载器是系统类加载器(AppClassLoader),在线程中运行的代码可以通过此类加载器来加载类和资源。jdbc加载示意图:
在这里插入图片描述
很明显了确实通过线程上下文类加载器加载的,实际上核心包的SPI类对外部实现类的加载都是基于线程上下文类加载器执行的,通过这种方式实现了Java核心代码内部去调用外部实现类。
通过getSystemClassLoader()获取类加载器来加载classpath路径下的类具有代码部署到不同服务时会出现问题,因为这些服务使用的线程上下文类加载器并非AppClassLoader。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值