类加载机制

首先,先了解一下,一个Java类是如何运行的。
在这里插入图片描述看到这幅图之后,我们知道了我们的Java文件首先由.Java文件编译成.Class文件然后被加载进入JVM中的。那么更多的问题便随之出现了。
一个类是如何被加载进JVM中的?一个类是被什么加载进JVM中的?一个类被加载了,是否需要被卸载?此时,就要讲起我们的类加载机制了。类加载机制_第1张图片
一、类的生命周期

首先就要了解到类的生命周期。
类加载机制_第2张图片从第一步到第五步就是类的加载。在Java8中,当一个类被加载以后,类的信息就会被我们创建的Oracle JVM(HotSpot)保存在相对应的MetaSpace当中。在Java7中存放在Perm Space中。
tips:在类中被static final修饰的变量会被立即赋值,并且放到MetaSpace当中。

比较值得说的是,在验证阶段。JVM会确保被编译的Class文件中的格式是否满足JAVA规范(细心的人都会看到,在class文件中的头部都会有一个cafe babe的Java验证),并且进行一系列语义分析以及,以及字节码验证等操作。

二、类加载器

类加载器,负责装入类。每一种类加载器,都有不同的分工。

1.Bootstrap Loader(核心类库加载器)
这个就是Java与C/C++之间的很标准的一道墙,核心类库加载器由C/C++实现,没有相对应的Java类。它会加载JRE_HOME/jre/lib中的目录。
2.Extension Loader(拓展类库加载器)
主要加载JRE_HOME/jre/lib/ext中的目录,JDK拓展包,或者用户配置的目录。
3.Application Loader(用户应用程序类加载器)
这个类加载器就是加载我们写的Java文件的类加载器,他会加载默认Java.class.path指定的目录。
或者是使用java命令加载的Java文件。
tips:
1.通过Java.lang.Class.getClassLoader()可以看到加载我们类的类加载器。如果是顶层的Bootstrap类加载器,就会显示null。
2.一个类不会重复加载。
类加载机制_第3张图片
那么,当一个类被加载以后,如果我们需要动态的获取一个类的信息,类似tomcat去动态加载JSP的时候(热加载),该怎么办呢?
tips:可以用两个类加载器,去加载一个类。

三、类卸载

什么时候类会被卸载?
1.当Class所有的实例都被GC。
2.加载该类的ClassLoader已经被GC。

//手写伪代码
//创建ClassLoader
ClassLoader classLoader = new ClassLoader();
Class littleClass = classLoader.loadClass();
//创建Class的一个实例
Object newInstance = littleClass.newInstance();

//在把以下两个对象置为null时下次系统GC的时候类就会被卸载
classLoader = null;
newInstance = null;

其实原理很简单,就是让GC对象无法找到GCROOTS,对象被进一步回收。

在JVM启动时候配置:-verbose:class就会输出类的加载与卸载的信息。

四、双亲委派机制
为了避免重复加载,由下到上逐级委托,由上到下逐级查找。
类加载机制_第4张图片
类加载器不会主动的去加载一个类,而是会委托给自己的上一级类加载器去加载这个类,当父类加载器无法加载的时候,才会让子类加载器进行加载。
tips:出于安全性角度考虑。如果我们可以自己写一个不一样的Object类,被加载到JVM中执行,它就是是一个很不安全的做法。

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