JVM类加载机制

JVM类加载机制,第1张

JVM类加载机制 类加载过程

详细链接: https://www.processon.com/view/link/61e31970e0b34d1be7f8ac96

ClassLoader.loadClass()的类加载过程 加载: 从磁盘上将.class的字节码文件加载到JVM内存中去,此时会做一些简单的校验,校验通过后,会生成一个java.lang.Class对象,作为这个类各种数据再方法区的入口验证: 校验字节码文件的正确性,看看是否符合JVM字节码规范,比如魔数,主次版本号等准备: 将类中的静态变量分配内存并且赋默认值解析: 将符号引用(比如方法名)转变为直接引用(JVM内存地址),这就是所谓的静态链接的过程 静态链接: 类加载期间,将符号引用转变为直接引用动态链接: 程序运行期间,将符号引用转变为直接引用,比如方法中调用方法,JVM解析的时候会对被调用的方法名指向一个内存地址,通过这个地址找到对应的方法,最常见的就是多态,有不同的实现,只有到运行的时候才知道 初始化: 对类的静态变量初始化为指定值,执行静态代码块 类被加载到方法区中包含 运行时常量池类型信息字段信息方法信息类加载器的引用对应class实例的引用 注意: 类加载机制是懒加载,部署war包使用时才会加载,静态代码块比构造函数先执行,类没加载完,不会调用构造函数 类加载器和双亲委派机制 类加载器

引导类加载器(BootStrap): 加载jre/lib目录下的核心类库

拓展类加载器(Ext): 加载支撑JVM运行的jre/lib/ext目录下的jar

应用程序类加载器(App): 加载classpath路径下的类包,主要是加载用户自己写的类

自定义类加载器: 加载用户自定义路径下的类。特殊需要的时候才自定义类加载器,比如Tomcat会自定义类加载器,默认是应用程序加载器

sum.misc.Launcher可以理解为所有类的父类加载器,C++先初始化Launcher类后,在通过此类生成拓展类、应用程序类加载器等

问题: 为什么引导类加载器不是Launcher类生成的

因为引导类加载器是由C++直接生成的对象 类加载器初始化过程 创建JVM启动器实例: sun.misc.Launcher,此类为单例模式,保证只有一个实例Launcher类创建两个类,ExtClassLoader和AppClassLoaderJVM默认使用Launcher的ClassLoader方法返回的加载器AppClassLoader的实例加载我们的应用程序 双亲委派机制

当应用程序类加载器加载某类时,如果没有找到,就会向上让扩展类加载器去加载如果扩展类加载器也没有该类,就会继续向上让引导类加载器去加载如果引导类加载器也没有该类,那么就向下继续委托如果都没有找到,那么就让应用程序类加载器去加载 为什么要先用应用程序类加载器去加载代码,而不是直接用引导类加载器 因为大部分的类都是用户自己定义编写的,也就是大部分的类文件都存放在应用程序类加载器的指定类路径下,如果不从这里开始会导致效率降低 什么是双亲委派机制 双亲委派机制就是加载某个类时先委托父加载器去寻找目标类,找不到再委托上层父加载器,如果所有父加载器都没有自己类路径下找到目标类,那么就会交给最开始的类加载器去加载该目标类 为什么要设计双亲委派机制 双亲委派机制可以避免类的重复加载沙箱安全机制,保证核心类不被篡改 全盘委托机制 全盘委托是指当一个ClassLoder装载一个类时,除非显示的使用另外一个ClassLoder,该类所依赖及引用的类也由这个ClassLoder载入 如何自定义类加载器 代码思路 继承java.lang.ClassLoader类重写ClassLoader.findClass()方法,此方法通过IO读取自定类文件路径重写ClassLoader.loadClass()方法,加载类 打破双亲委派机制 加载一个类,不使用父加载器,直接由自定义类加载器加载类代码思路 重写ClassLoader.loadClass()方法后在里面调用父加载器的方法处添加判断逻辑,如果是自定义类路径,就调用自定义的findClass方法 Tomcat为什么要打破双亲委派机制 对于一个web容器来说,可能需要部署多个应用程序,不同的应用程序可能依赖相同类库的不同版本,但是双亲委派机制已经实现了避免重复类加载,因此要保证每个版本的类库是独立的,要保证相互隔离部署在同一个web容器中相同类库的版本可以共享,否则多个应用程序此时都是同一类库的版本,会导致进行加载多次,浪费资源处于安全方面考虑,Tomcat也有自己的类库,也需要进行隔离处理,否则会导致与应用程序的类库混淆每个jsp对应一个类加载器,这样是为了方便热部署 Tomcat这种类加载机制是否违背了双亲委派机制 很显然是的,Tomcat为了实现隔离性,每个webappClassLoader加载自己目录下的类文件,不会传递给父加载器,打破了双亲委派机制首先自己尝试去加载某类,如果找不到再代理给父加载器,其目的是优先加载web应用自己定义的类,它父类加载器就是AppClassLoaderweb应用是通过Class.forName()调用交给系统类加载器的,因为Class.forName的默认类加载器是系统类加载器 Tomcat怎么实现热加载 单独用一个线程时刻去监听jsp文件路径下文件夹的变动,比如说1s监听一次,如果有变动,把之前的类加载器置空,再重新赋值最新的类加载器,之前的等待gc回收 Tomcat类加载图

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/web/1295111.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-10
下一篇 2022-06-10

发表评论

登录后才能评论

评论列表(0条)

保存