是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战
运行时数据区
JVM用来储存加载的类信息、常量、静态变量、编译后的代码等数据。
虚拟机规范中这是一个逻辑区划。具体实现根据不同虚拟机来实现。
如:Oracle的HotSpot在java7中方法区放在永久代,java8放在元数据空间,并且通过GC机制对这个区域进行管理。
类生命周期
问题:class是怎么加载的呢 ?
类加载器
类加载器负责装入类,搜索网络、jar、zip、文件夹、二进制数据、内存等指定位置的类资源。一个java程序运行,最少有三个类加载器实例,负责不同类的加载。
验证问题
- 查看类对应的加载器
通过JDK-API进行查看:java.lang.Class.getClassLoader()
返回装载类的类加载器
如果这个类是由bootstrapClassLoader加载的,那么这个方法在这种实现中将返回null
- JVM如何知道我们的类在何方
class信息存放在不同的位置,桌面jar、项目bin目录、target目录等
查看openjdk源代码:sun.misc.Launcher.AppClassLoader
结论:读取java.class.path配置,指定去哪些地址加载类资源
验证过程:利用jps、jcmd两个命令
- jps查看本机JAVA进程
- 查看运行时配置:jcmd + 进程号 + VM.system_properties
- 类不会重复加载
类的唯一性:同一个类加载器。类名一样,代表是同一个类
识别方式:ClassLoader Instance id + PackageName + ClassName
验证方式:使用类加载器,对同一个class类的不同版本,进行多次加载,检查是否会加载到最新的代码。
结论不会
- 类什么时候会被卸载
满足如下两个条件:
- 该Class所有的实例都已经被GC
- 加载该类的ClassLoader实例已经被GC
验证方式:jvm启动中增加 -verbose:class参数,输出类加载和卸载的日志信息
-
双亲委派模型
为了避免重复加载,由下到上逐级委托,由上到下逐级查找。
首先不会自己去尝试加载类,而是把这个请求委派给父加载器去完成;
每一个层次的加载器都是如此,因此所有的类加载请求都会传给上层的启动类加载器。
只有当父加载器反馈自己无法完成该加载请求(该加载器的搜索范围中没有找到对应的类)时,子加载器才会尝试自己去加载。
注:类加载器之间不存在父类子类的关系,“双亲”是翻译,可以理解为逻辑上定义的上下级关系。