持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第17天,点击查看活动详情
类加载机制
类加载的过程
- 类加载流程:若加载某类A, 则在操作系统底层调用jvm.dll文件创建java虚拟机(c++实现)
- 与此同时会创建一个引导类加载器的实例()c++实现
- 然后C++调用Java代码创建启动器实例sun.misc.Launch(这个类由引导类加载器负责加载从而创建其他类加载器,)c++语言调用sun.misc.Launch.getLauncher()方法
此方法会返回launcher ,实际上表示Launch类在加载的时候就已经初始化;
类加载器
-
引导类加载器
负责加载jdk的核心类库文件,加载Launch类,从而加载其他的类加载器
-
扩展类加载器
负责加载JDK扩展类包下的文件,是AppClassLoader的父加載器;
3. 应用程序类加载器
主要就是加載ClassPath 下的包,也就是开发的类文件;
-
自定义类加载器
继承ClassLoader 实现自己的类加载逻辑
双亲委派机制
当jvm需要加载某个类时候,会首现委托给其父加载器去加载,父加载器在自己已经加载类中查,如果加载过,则直接返回,没加载过再继续向上委托,在经历一盘判断过程,如果当前加载类路径下没有这个类在继续向下,最终由加载该类所在文件路径下的加载器自己加载;
这种加载方式可以避免类的重复加载,父已经加载了该类时,子ClassLoader就不用再加载一 次,保证类只被加载一次;
保证JDK核心类库的安全;
加载源码
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
loadClass的类加载流程:
-
加载:读取字节码文件,懒加载方式,使用到类时才会加载,加载过程中会在方法区有一个java.lang.Class对象,作为这个类关联数据的引用地址 ;
-
验证:校验加载得到的字节码文件的正确性 ;
-
准备:给类的静态变量分配内存,并赋予默认值
-
解析:将符号引用替换为直接引用,该阶段会把一些静态方法(符号引用,比如 main()方法)替换为指向数据所在内存的指针(直接引用),这是所谓的静态链接过 程(类加载期间完成),动态链接是在程序运行期间将符号引用替换为直接引用
-
初始化:对类的静态变量初始化为设定的值,执行静态代码块
类加载完成后,这个类到类加载器实例的引用 对应的class实例的引用,类加载器在加载类信息放到方法区中后,会创建一个对应的Class 类型的实例对象存放到堆中的新生代;