jvm(2)---类加载机制

1.类加载:类加载器将class文件加载到虚拟机的内存
加载:在硬盘上查找并经过IO读入字节码文件
链接:执行校验、准备、解析步骤
校验:校验字节码文件的正确性
准备:给类的静态变量分配内存,并赋予默认值
解析:类装载器装入类所引用的其余全部类
初始化:对类的静态变量初始化为指定的值,执行静态代码块java

 

2.类加载器spring

启动类加载器(BootstrapClassLoader):负责加载JRE的核心类库,如jre目标下的rt.jar,charsets.jar等
扩展类加载器(ExtensionClassLoader):负责加载JRE扩展目录ext中JAR类包
系统类加载器(ApplicationClassLoader):负责加载ClassPath路径下的类包
用户自定义加载器(CustomClassLoader):负责加载用户自定义路径下的类包jvm

执行以下代码,查看对应的类加载器:ide

package com.nijunyang.spring;


import com.sun.crypto.provider.BlowfishCipher;

/**
 * @author: create by nijunyang
 * @date:2019/6/16
 */
public class ClassLoaderTest {
    public static void main(String[] args)
    {
        System.out.println(String.class.getClassLoader());
        System.out.println(BlowfishCipher.class.getClassLoader().getClass().getName());
        System.out.println(ClassLoaderTest.class.getClassLoader().getClass().getName());
        System.out.println(ClassLoader.getSystemClassLoader().getClass().getName());
    }
}

 

   -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------spa

能够看到String的类加载器null,由于String是在java核心包rt.jar里面这里面东西是由启动类加载器加载的,而启动类加载器是由C/C++实现的,根本不在JDK里面。
BlowfishCipher的类加载器是ExtClassLoader,而这个类正是Jre扩展目录ext中jar包所在的类
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

3.类加载机制--全盘委托和双亲委派机制3d

全盘委托:当一个ClassLoader加载一个类时,除非显示的使用另外一个ClassLoader,该类所依赖和引用的类也由这个ClassLoader载入,好比说A依赖B,那么B的加载器和A的加载器同样。对象

双亲委派:指先委托父类加载器寻找目标类,在找不到的状况下在本身的路径中查找并载入目标类,感受说父类加载器不是很合适,由于没有这一层关系,感受更像是上下级关系。委托上级加载器寻找目标类。blog

双亲委派的好处:ip

1.避免类重复加载,上级加载了,下级就不须要再加载内存

2.由于核心API都有固定的加载器,能够防止核心库被篡改: 自定义一个String类,一样在java.lang包下,运行代码会发现启动报错,实际加载的java.lang.String类并无main方法,说明实际加载的String类并非咱们自定义的String类,而是由于双亲委派机制,往上委托到启动类加载器,去加载rt.jar里面的String类

 

4.类加载过程

实际上jvm对class文件是按需加载的,须要的时候才加载(运行时动态加载),并不是一次所有加载进去,jvm启动参数加上:-verbose:class 查看类加载

package com.nijunyang.spring;


/**
 * @author: create by nijunyang
 * @date:2019/6/16
 */
public class ClassLoaderTest {
    static {
        System.out.println("静态块执行");
    }
    public static void main(String[] args) throws InterruptedException {
        Thread.sleep(3000);
        System.out.println(System.currentTimeMillis());
        new A();
        System.out.println("A对象建立完毕");
        new B();
    }
}

 

从结果中咱们能够看到

1.从本地/E:/IdeaProject/tuling/spring/target/classes/下面去加载当前运行类ClassLoaderTest.class文件

2.初始化类,执行静态代码块

3.main方法运行,睡了5s以后打印当前时间,当咱们new A的时候才去本地加载A.class文件到内存,再实例化A

4.A建立完毕以后,再去加载B.class,完成B的初始化

相关文章
相关标签/搜索