类加载机制

1、类生命周期

a.加载:读取.class文件二进制内容
b.验证:class文件格式规范、语义分析、引用验证、字节码验证
c.准备:分配内存、设置类static修饰的变量初始值
d.解析:类、接口、字段、方法等解析
e.初始化:为静态变量赋值、执行静态代码块
f.使用:创建实例对象
g.卸载:从JVM方法区中卸载

2、类加载器

类加载器负责装入类,搜索网络、jar、zip、文件夹、二进制数据、内存等指定位置的类资源。Java程序运行最少有三个类加载器实例,负责不同类的加载。

1>Bootstrap Loader:核心类库加载器。C/C++实现,无对应Java类,顶层类加载器。加载JRE_HOME/jre/lib目录,或用户配置的目录。JDK核心类库:rt.jar。
2>Extension Class Loader:拓展类库加载器。实例:sun.misc.Launcher.ExtClassLoader,父加载器是Bootstrap Loader。加载JRE_HOME/jre/lib/ext目录,JDK拓展包,或用户配置的目录。
3>Application Class Loader:用户应用程序加载器。实例sun.misc.Launcher.AppClassLoader,父加载器是ExtClassLoader。加载java.class.path指定的目录,用户应用程序class-path或者java命令运行时参数-cp。

通过JDK-API进行查看:java.lang.Class.getClassLoader()返回装载类的类加载器。如果这个类是由Bootstrap ClassLoader加载的,由于是C/C++写的并没有Java实例,getClassLoader方法会返回null。

两个命令
jps:查看本机Java进程
jcmd:查看运行时配置:jcmd pid(进程号) VM.system_properties

类不会重复加载
类的唯一性:同一个类加载器,类名一样,代表是同一个类。
识别方式:ClassLoader Instance id + PackageName + ClassName

3、类的卸载

满足下面两个条件时类会被卸载:
a.该Class所有的实例都已经被GC
b.加载该类的ClassLoader实例已经被GC
验证方式:jvm增加启动参数:-verbose:class,输出类加载和卸载的日志信息

静态方法、静态代码块,在类第一次被实例化时加载。类加载器加载类时不会加载其中的静态方法、静态代码块。

4、双亲委派模型

  Bootstrap      --查找--> ext拓展类库 --查找--> app用户应用程序 --查找-->   最低端
顶层类加载器  <--委托--     类加载器  <--委托--         类加载器      <--委托--  子类加载器

为了避免重复加载,从下到上逐级委托,从上到下逐级查询。
每一层的加载器首先不会自己去尝试加载类,而是把这个请求委派给上层的父加载器去完成。
当父加载器反馈自己无法完成该加载请求时(该加载器的搜索范围中没有找到对应的类),子加载器才会尝试自己去加载。
类加载器之间不存在父类子类的关系,“双亲”只是逻辑上定义的上下级关系。

热加载
每次都创建一个新的类加载器。因为在一个类加载器中,类不会重复加载,只加载一次,那么每次创建新的类加载器,就可以在代码有变化时,重新去加载类,实现热加载的效果。
Tomcat加载jsp文件就是这样实现,jsp修改后转化为java文件,再编译成class文件,当监测到jsp文件有变化时,就创建一个新的ClassLoader。
 

你可能感兴趣的:(Jvm,类加载)