首页 > 编程知识 正文

spring类加载器,启动类加载器

时间:2023-05-04 15:25:19 阅读:32204 作者:4911

文章目录序言1 .常用类加载器2 .父母委托模型2.1 .父母委托模型介绍2.2 .通过父母委托模型实现源代码分析2.3 .父母委托模型的好处2.4 .不想使用父母委托模型该怎么办? 3 .自定义类加载器4 .总结

前言

加载过程:加载-连接-初始化连接过程为验证-准备-解析

数组类型不是由类加载器创建的,而是直接由Java虚拟机创建的。

的所有类都由类加载器加载,加载的作用是将. class文件加载到内存中。

类加载过程在这里没有详细描述,如果有需要的合作伙伴,请去看这篇文章哦: 《Java中类的一生是如何度过的?》

1 .常用的类加载器JVM内置三个重要的类加载器(ClassLoader ),除BootStrapClassLoader之外的所有类加载器都用Java实现,全部用Java.lang.class

BootStrapClassLoader(启动类加载器):顶级负载类。 通过%JAVA_HOME%/lib目录中的jar包和类实现,或通过加载由-Xbootclasspath参数指定的路径中的所有类的c实现。ExtensionClassLoader(扩展类加载器):主要在目录%JRE_HOME%/lib/ext%目录下的jar包和类,或在java.ext.dirs系统变量指定的路径下的jarAppClassLoader(应用程序类加载器):用于加载当前APP应用程序classpath下的所有jar包和类的用户加载器。 2 .父母委托模型2.1 .父母委托模型每一个类都有一个对应它的类加载器。系统中的ClassLoader在协同工作时恢复默认值并使用3358www.Sina.com/。 也就是说,当加载类时,系统首先确定是否加载了当前类。 加载的类直接返回。 否则,我不会尝试加载。 由于所有请求必须最终传递到顶层启动类加载器BootStrapClassLoader (加载时首先将处理委托给父类加载器的loadClass ) )方法。 如果父类加载器无法处理,则自行处理。 如果父加载器为null,则启动类加载器BootStrapClassLoader用作父加载器。

每个类都有一个父类加载器,要验证:

public class test (publicstaticvoidmain (string [ ] args ) system.out.println ) ) test的类加载器是) system.out.println('test父类的父亲类加载器为' Test.class.getClassLoader ().getParent (.get parent ).get parent ) ) ); }输出如下。

Test的类加载器是sun.misc.launcher $ app class loader @ 18 B4 AAC2test的父类的类加载器是sun.misc.launcher $ ext class loader @

ApplicaionClassLoader的父类加载器是ext类加载器,ext类加载器的父类加载器是null,null并不意味着ext类加载器没有父类加载器

其实,这位父母的翻译很容易被别人误解。 我们一般理解的父母是父母。 这里的父母更多地表达了“父母一代”的人。 其实并不是有Mother ClassLoader和Father ClassLoader。 另外,类加载器之间的“父子”关系也不是通过继承来表示的,而是由“优先级”决定的。

2.2 .实现父母委托模型源代码分析的父母委托模型实现代码非常简单,逻辑也非常清晰,全部集中在java.lang.ClassLoader的loadClass ()上。

私有文件类加载器父项; 保护类? 加载类(string name,boolean resolve ) throwsclassnotfoundexception (synchronized ) getclassloadinglock ) /首先

lass<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) {//父加载器不为空,调用父加载器loadClass()方法处理 c = parent.loadClass(name, false); } else {//父加载器为空,使用启动类加载器 BootstrapClassLoader 加载 c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { //抛出异常说明父类加载器无法完成加载请求 } if (c == null) { long t1 = System.nanoTime(); //自己尝试加载 c = findClass(name); // 这是定义类加载器;记录统计数据。 sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; }} 2.3. 双亲委派模型的好处

双亲委派模型保证了 Java 程序的稳定运行,可以避免类的重复加载( JVM 区分不同类的方式不仅仅根据类名,相同的类文件被不同的类加载产生的是两个不同的类),也保证了 Java 的核心 API 不被篡改。如果没有双亲委派模型,而是每个类加载器加载自己的话就会出现一个问题,比如我们编写一个称 java.lang.Object 类的话,那么程序运行的时候,系统就会出现多个不同的 Object 类。

2.4. 如果我们不想使用双亲委派模型怎么办?

自定义加载器的话,需要继承 ClassLoader 。如果我们不想打破双亲委派模型,就重写 ClassLoader 类中的 findClass() 方法即可,无法被父类加载器加载的类最终会通过这个方法被加载。但是,如果想打破双亲委派模型则需要重写 loadClass() 方法

3. 自定义类加载器

除了 BootStrapClassLoader ,其他的类加载器均由 Java 实现且继承自 java.lang.ClassLoader 。如果我们要自定义自己的类加载器,很明显需要继承 ClassLoader。

4. 总结

本篇文章讲解了 Java中类加载器,代码和笔记由于纯手打,难免会有纰漏,如果发现错误的地方,请第一时间告诉我,这将是我进步的一个很重要的环节。以后会定期更新算法题目以及各种开发知识点,如果您觉得写得不错,不妨点个关注,谢谢。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。