Java类加载机制
2021/6/12 20:24:18
本文主要是介绍Java类加载机制,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
JVM基础生命周期流程图
classLoader.loadClass()的类加载(除引导类,所有类都一样)
- 加载:通过IO查找读取磁盘上的字节码文件,在调用到类才进行加载(调用类的方法,或者new 一个实例对象),会在内存创建一个Class对象,在方法区中代表这个类(用于获取该类的各种数据)。
- 验证:校验字节码文件是否符合规范。
- 准备:将类中的
非最终静态变量
分配内存地址,并赋予类型
默认值(根据类型给予,与实际赋值无关)。最终静态变量
会直接进行赋值操作,无需进行类型初始值赋予。 - 解析:将符号引用替换为直接引用,将一些静态方法(字符)替换为内存中的地址或句柄,即静态链接,而动态链接是指在程序运行期间将符号引用替换为直接引用。
- 初始化:对类的非最终静态变量初始化赋值(赋予
类中指定的初始值
,代替类型初始值
),并且执行静态代码块。
注意:在未调用如何方法,未new对象的情况下。不会加载类,即只声明类如:
//不会加载类 User user=null; //创建实例,会加载类 User user=new User(); //调用方法,会加载类 User.staticMethod();
能够获取到它的Calss对象,就会加载类
类加载器初始化
类的加载主要通过类加载器进行实现,而java包含的加载器如下:
- 引导类加载器(
实例sun.misc.Launcher
):由C++实现,用于加载支撑JVM运行的核心类库(Jre的lib目录下,如rt.jar、charsets.jar) - 扩展类加载器(
sun.misc.Launcher.ExtClassLoader
):由Java实现,用于加载支撑JVM运行的ext扩展目录中的jar包(Jre的lib目录下ext目录) - 应用程序类加载器(
sun.misc.Launcher.AppClassLoader
):由Java实现,用于加载ClassPath路径下的类包,也就是我们编程所写的类包。 - 自定义加载器:由Java实现,可以自己进行实现,常见的有Tomcat的加载器。
ExtClassLoader(扩展类加载器)在Launcher的构造方法中被设置为了AppClassLoader(应用类加载器)的父类加载器
而ExtClassLoader(扩展类加载器)的父类加载器由于是bootstrap(引导类加载器)而无法在Java中表示故被设置为null
另外bootstrap(引导类加载器)由C++进行加载,无需进行类加载
双亲委派机制
指类是如何判别在那个加载器中被加载
- 寻找是否加载阶段
- 进行加载阶段
实际上其原理就是在AppClassLoader.loadClass方法中进行执行的,主要流程:
- 检查该类是否已经被本
类加载器
加载,已加载直接返回(被加载的对象) - 诺未加载则判断是否存在父
类加载
器,存在即调用父类加载器
的loadClass方法,诺无父类加载器
(说明该加载器为引导类加载器),调用bootstrap类加载器
加载. - 诺到达bootstrap
类加载
器,并且bootstrap也未加载该类,则调用findClass方法尝试加载该类. - 诺加载到该类,直接返回。未加载该类则进行向下委派,由子
类加载器
调用findClass方法进行尝试加载。
注意:findClass方法不是类加载器的方法而是类加载器父类URLClassLoader的方法,其功能为在类加载器路径里查找并加载该类
- 双亲委派的作用
- 沙箱安全机制: 你自己写的同包名同类的java核心类时,双亲委派机制依旧会加载核心库中的类,而不会加载你所创建的类,从而保证核心类库不被随意篡改。
- 避免重复加载;当
子类加载器
加载过该类就无需向上委托。而当父类加载器
加载了该类直接返回,而子类加载器
无需加载,保证有且只有一个类加载器
加载了该类,并且该类只被加载了一次。保证被加载类的唯一性
全盘委托机制(全盘负责委托机制)
- 当ClassLoder(类加载器)加载一个类时,该类所依赖或引用的类也由该ClassLoder(类加载器)加载,除非指定使用另一个ClassLoder(类加载器)
实际上我学习的时候就有疑问,java核心类是最常被调用的类,那么如果每次都需要从应用类加载器从下到上找一次,会造成不必要的性能消耗。然而这个机制保证了不必要的消耗。
打破双亲委派机制
之所以要打破双亲委派机制,是为了实现不同的加载类的方式,例如Tomcat的war包就打破了双亲委派机制,从而实现运行不同的war包而不会互相干扰。
- 基本要求
- 自定义类加载器
- 自定义类加载器重写loadClass方法(
该方法中实现了双亲委派机制
)
注意:Tomcat类加载器打破了双亲加载机制,除无法加载的java核心类,都由Tomcat类加载器进行加载。
- webappClassLoader加载自己的目录下的class文件,不会传递给父
类加载器
,打破了双亲委派机制 - 因为打破双亲委派机制,即重写了findClass(),所以不会向父
加载器
寻找Class,即不会传递给父类。 - webappClassLoader重写了loadClass()方法,不再遵循双亲委派,而是自己加载所有类(不包括java核心类)
这篇关于Java类加载机制的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-06-05做软件测试需要懂代码吗?
- 2024-06-0514-ShardingSphere的分布式主键实现
- 2024-06-03为什么以及如何要进行架构设计权衡?
- 2024-05-31全网首发第二弹!软考2024年5月《软件设计师》真题+解析+答案!(11-20题)
- 2024-05-31全网首发!软考2024年5月《软件设计师》真题+解析+答案!(21-30题)
- 2024-05-30【Java】百万数据excel导出功能如何实现
- 2024-05-30我们小公司,哪像华为一样,用得上IPD(集成产品开发)?
- 2024-05-30java excel上传--poi
- 2024-05-30安装笔记本应用商店的pycharm,再安排pandas等模块,说是没有打包工具?
- 2024-05-29java11新特性