JVM—类加载器ClassLoader

类加载器

  • 根加载器:加载$JAVA/HOME/jre/lib下的class文件,就是java1.0开始的哪些原始的java 文件,如 Object类、String、Thread这些。当加载rt.jar这个jar包下的launcher类时候,会去加载launcher类的内部类ExtClassLoader 和AppClassLoader,所以拓展类加载器和系统类加载器都是启动类加载器加载的。

  • 拓展加载器:$JAVA/HOME/jre/lib/ext/*.jar 加载java的拓展class文件,比如javax开头的包,是jdk团队在每个版本拓展功能时候加入的class文件

  • 应用程序加载器: 加载我们这些使用使用开发编译后的这些class文件

User-DefinedClassLoader2
SystemClassLoader
User-DefinedClassLoader1
User-DefinedClassLoader3
ExtensionClassLoader
BootstrapClassLoader

类加载器示例

如果获取一个类的加载器:
对象.getClass.getClassLoader();

public class ClassLoaderDemo1 {

    public static void main(String[] args) {
        Object o = new Object();
        //获取classLoader的方法,由于object是根加载器加载,根加载器是无法访问的,为null
        System.out.println("Object的类加载器"+o.getClass().getClassLoader() );
        //由于根加载器已经是顶级的,因为没有父类,此处会报空指针异常
        //System.out.println(o.getClass().getClassLoader().getParent() );
        ClassLoaderDemo1 clDemo = new ClassLoaderDemo1();
        System.out.println(clDemo.getClass().getClassLoader() );
        System.out.println( clDemo.getClass().getClassLoader().getParent());
        System.out.println(clDemo.getClass().getClassLoader().getParent().getParent() );

    }
}
/*打印结果:
Object的类加载器null
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@6f94fa3e
null
说明:由于ClassLoaderDemo1是自己编写的,因此是有appClassLoader来加载,而它对应的父类是拓展加载器ExtClassLoader,
ExtClassLoader的加载器的父类是 根加载器 BootstrapClassLoader,但该类不可访问,因此访问null
另外:所有的类加载器打印出来都有一个sun.misc.Launcher,这个是java虚拟机入口的引用类
*/

双亲委派机制

先看示例:
自己建一个java.lang的包,然后创建一个String的类,去执行。

public class String {
    public static void main(String[] args) {
        System.out.println("test..." );
    }
}
//打印结果:
//错误:在类java.lang.String中找不到main方法,请将main方法定义为:public static void main(Stirng[] args),否则JavaFX 应用程序类必须拓展javafx.application.Application

报错原因 : 是jvm找到的并不是当前自己创建的这个java.lang.String,而是读取的rt.jar包中jdk自定义的java.lang.String。这里面就涉及到jvm的加载机制,即双亲委派机制

概念
当一个类加载器收到了加载类的请求,它首先不会自己去尝试加载这个类,而是把这个类委派给父类去完成,每一个层次类加载器都是如此,因此所有的加载请求都应该传送给bootstrap classloader中加载,只有当父类加载器在它的加载路径下找不到所需加载的class,子类加载器才会尝试自己去加载。
好处
双亲委派的好处就是保证了不同的类加载器最终得到的都是同样一个Object对象,就比如加载位于rt.jar包中的类java.lang.Object。不管是哪个加载器加载这个类,最终都是委托给顶层bootstrap classLoader去进行加载的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值