JVM——类加载器

一、类加载器的定义 

在类加载过程中,通过一个类的全限定名来获取描述该类的二进制字节流,实现这个动作的代码成为“类加载器”。

二、类加载器的分类

类加载器分为引导类加载器和自定义加载器,从概念上讲,自定义加载器一般是指程序中由开发人员自定义的一类加载器,在java虚拟机规范中,定义自定义加载器是指将继承ClassLoader的类加载器都划分为自定义类加载器。

 三、双亲委派模型

上面类加载器的分类是站在Java虚拟机的角度分的,但是站在Java开发人员的角度来看,要分为三层类加载器,如图

 

 注意:四者关系是包含关系,不是上层下层,也不是子父类的继承关系

 使用Java API 获得类加载器

        //获取系统类加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);//sun.misc.Launcher$AppClassLoader@b4aac2

        //获取扩展类加载器
        ClassLoader extClassLoader = systemClassLoader.getParent();
        System.out.println(extClassLoader);//sun.misc.Launcher$ExtClassLoader@16d3586

        //获取启动类加载器
        ClassLoader bootstrapClassLoader = extClassLoader.getParent();
        System.out.println(bootstrapClassLoader);//null

        //对于用户自定义类:默认使用系统类加载器加载
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
        System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@b4aac2

        //对于String:使用引导类加载器进行加载的 -->系统的核心类库,都是引导类加载器进行加载的
        ClassLoader stringClassLoader = String.class.getClassLoader();
        System.out.println(stringClassLoader);//null

 注意:启动类加载器无法被Java程序直接引用,用户在获取启动类加载器直接用null代替

3.1 启动类加载器

(1)启动类加载器使用c/c++语言实现的,嵌套在jvm虚拟机内部

(2)它用来加载Java的核心库(JAVA_HOME/jre/lib/rt.jar、resource.jar或者sun.boot.class.path路径下的内容),用于提供JVM自身需要的类

(3)并不继承java.lang.ClassLoader,没有父加载器

(4)扩展类加载器和应用程序加载器,也是由启动类加载器加载

(5)出于安全考虑,Bootstrap启动类加载器只加载包名为java、javax和sun等开头的类

3.2 扩展类加载器 

(1)扩展类加载器使用java语言编写,继承于ClassLoader类

(2)父类加载器为启动类加载器

(3)从java.ext.dirs系统属性所指定的目录中加载类库,或从jdk的安装目录的jre/lib/ext子目录(扩展目录)下加载类库。

(4)如果用户创建的JAR放在此目录下,也会自动由扩展类加载器加载

 3.3 应用程序类加载器

 (1)由java语言编写,派生于ClassLoader类,父类加载器为扩展类加载器

(2)负责加载环境变量classpath或系统属性java.class.path指定路径下的类库

(3)它是java程序默认的类加载器

        System.out.println("********启动类加载器*******");
        URL[] urLs = Launcher.getBootstrapClassPath().getURLs();
        Arrays.stream(urLs).forEach(url -> System.out.println(url.toExternalForm()));

        System.out.println("********扩展类加载器**********");
        String extDirs = System.getProperty("java.ext.dirs");
        Arrays.stream(extDirs.split(";")).forEach(System.out::println);

3.4 自定义类加载器

在我们的开发中,为什么需要自定义类加载器呢?

隔离加载类

修改类加载方式

扩展加载源

防止源码泄露

使用用户自定义加载器加载类,JVM会将这个类加载器的一个引用作为类型信息的一部分保存在方法区中。

3.5 双亲委派模型的工作原理

如果一个类收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。这样做的好处java中的类随着它的类加载器一起具备了一种带优先级的层次关系,保护程序安全。

判断两个class对象是否是同一个类的必须条件

(1)类的完整类名必须一致,包括包名

(2)加载这个类的ClassLoader(指的ClassLoader实例对象)必须相同

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值