1.类的加载过程
JVM将类加载过程分为三个步骤:
装载(Load):
将.class文件通过IO流的方式加载到内存当中
1.将.class文件字节码内容加载到内存当中
2.先会将静态数据转换成方法区中的运行的数据结构
3.在堆内存当中生成一个代表这个类的Class对象,这个Class类的对象就是作为方法区数据访问的入口
链接(Link):三个步骤如下图
1.验证阶段:验证字节码文件的准确性,包含文件格式,元数据,符号引用,字节码等等
2.准备阶段:给类中的静态变量分配内存,并赋予初始值
3.解析阶段:将虚拟机常量池的符号引用替换成字节引用的过程
初始化(Initialize)
初始化过程就会对类中的静态变量初始化为指定的值,执行静态代码块,执行构造器
类的加载
类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个这个类的java.lang.Class对象,用来封装类在方法区类的对象。
类加载器的种类
VM的类加载是通过ClassLoader及其子类来完成的,类的层次关系和加载顺序可以由下图来描述:
2)Extension ClassLoader
负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包
3)App ClassLoader
负责记载classpath中指定的jar包及目录中class
4)Custom ClassLoader
属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader
加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。
类加载机制
JVM的类加载机制主要有如下3种。
全盘负责:
所谓全盘负责,就是当一个类加载器负责加载某个Class时,该Class所依赖和引用其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入。
双亲委派:
所谓的双亲委派,则是先让父类加载器试图加载该Class,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类。通俗的讲,就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父加载器,依次递归,如果父加载器可以完成类加载任务,就成功返回;只有父加载器无法完成此加载任务时,才自己去加载。
缓存机制:
缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存区中搜寻该Class,只有当缓存区中不存在该Class对象时,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存入缓冲区中。这就是为很么修改了Class后,必须重新启动JVM,程序所做的修改才会生效的原因。
如何破坏双亲委派机制
为什么要破坏双亲委派机制:父加载器需要委托子加载器在其进行加载
如何破坏:
1.重写ClassLoad类中的loadClass方法,指定加载哪一个类
2.手动调用系统类加载器
Thread.currentThread().getContextClassLoader();
3.重写findClass
监控类加载过程
在当前启动类当中加入-verbose:class参数,启动则可以看到整个类加载的过程
热部署
时时检测类,如果类发生更改则自动进行重新编译,编译之后重新加载该类