类加载器

目录

1. 类加载的时机

2. 三种类加载器

2.1 引导类加载器

2.2 扩展类加载器

2.3 应用类加载器

2.4 获取类加载器的Java代码

3. 类加载器的双亲委派

4. Class文件的对象


1. 类加载的时机

(1)创建类对象

(2)访问类的静态变量或静态方法

(3)创建某个类的子类对象

(4)直接运行某个类中的main()方法

(5)反射

       以上5个情况,只要有1个出现,那么类的加载器就会将这个类的class文件加载到内存中,我们就可以使用这个类了。

接下来,介绍三种类加载器(引导、扩展、应用类加载器),并且通过代码去获取这三种类加载器。(类加载器也是类对象)。

2. 三种类加载器

2.1 引导类加载器

       引导类加载器BootClassLoader

       是C++语言编写(与JAVA无关),负责加载JDK核心类库,引导类加载器在JVM内部,开发人员是不能直接操作的。

       核心类库位置(jdk安装目录下):\jdk\jre\lib\rt.jar

2.2 扩展类加载器

扩展类加载器ExtClassLoader:

Java语言编写的类加载器,负责加载JDK扩展类库,类库位置\jdk\lib\ext\下的jar包。

2.3 应用类加载器

应用类加载器AppClassLoader:

Java语言编写的类加载器,负责加载我们定义的类和第三方jar包中的类。

2.4 获取类加载器的Java代码

关于以上3种类加载器的获取方法如下代码所示:

注意:AppClassLoader 和 ExtClassLoader这两个类加载器都继承自:URLClassLoader
但是,AppClassLoader的.getParent()方法的结果却是ExtClassLoader,这并不是说明他们是继承关系(它们继承自同一个父类:URLClassLoader)。

package com.lmy.classloader;
import sun.net.spi.nameservice.dns.DNSNameService;

/**
 JDK加载器
 (1)String类 属于JDK核心类库中的类,由于该类的加载器是C++编写的(没有继承ClassLoader类),通过java代码看不到该类加载器
 (2)DNSNameService类 属于JDK扩展类库,它的类加载器为sun.misc.Launcher$ExtClassLoader  其父类为:URLClassLoader
 (3)MyClassLoader类是程序员自己写的类,它的类加载器为sun.misc.Launcher$AppClassLoader 其父类为:URLClassLoader
 注意:AppClassLoader 和 ExtClassLoader这两个类加载器都继承自:URLClassLoader
 但是,AppClassLoader的.getParent()方法的结果却是ExtClassLoader,这并不是说明他们是继承关系(它们继承自同一个父类:URLClassLoader)
 */
public class MyClassLoader {
    public static void main(String[] args) {
        //获取String类的加载器(属于核心类库):该类的class属性的.getClassLoader()方法
        ClassLoader classLoader = String.class.getClassLoader();
        System.out.println(classLoader); //C++编写的该类,java代码中看不到结果

        //获取DNSNameService类的加载器(属于JDK扩展类库)
        ClassLoader classLoader1 = DNSNameService.class.getClassLoader();
        System.out.println(classLoader1); //该类加载器ExtClassLoader最终的父类就是ClassLoader类

        //获取MyClassLoader类的加载器(属于程序员自己写的类)
        ClassLoader classLoader2 = MyClassLoader.class.getClassLoader();
        System.out.println(classLoader2); //该类加载器AppClassLoader最终的父类就是ClassLoader类
        //看一下AppClassLoader的getParent()的结果竟然是:ExtClassLoader
        System.out.println(classLoader2.getParent()); //这并不是说明他们是继承关系(真相是:它们继承自同一个父类:URLClassLoader)
    }
}

3. 类加载器的双亲委派

总的来说,“双亲委派”指的是:“先问双亲:该类加载任务归不归它们管,如果都不管,AppClassLoader类加载器最终负责加载该类”。如果这样讲解感觉有些抽象的话,通过如下的例子进行理解:
       命令行:java Test 运行该类,自定义的Tset类被加载进内存的过程如下(涉及双亲委派):
(1)情景一
       Test类中使用了String类,关于String类的加载问题,理论上应该交给AppClassLoader这个类加载器来完成,
而实际上,AppClassLoader类加载器将这个加载任务交给它的“双亲”(Ext和Boot):
先交给ExtClassLoader类加载器,但是发现“String类的加载不归我管”
然后ExtClassLoader类加载器把这个加载任务进一步交给BootClassLoader加载器,发现该任务“确实归我管”,于是由BootClassLoader加载器完成对String类的加载。
(2)情景二
        接下来,又创建了新的对象test,由于该类是自己定义的,所以还是让应用类加载器 AppClassLoader加载进内存,
而实际过程是这样的:AppClassLoader类加载器不会直接加载该类,而是先交给ExtClassLoader类加载器,它发现该类“不归我管”,再交给BootClassLoader加载器,它发现该类“也不归我管”时,最后才由AppClassLoader类加载器将Test类加载进内存。

4. Class文件的对象

使用一个类,就需要用“类加载器”把这个类加载到内存中。 假如这个类是我们自己写的,AppClassLoader类加载器先通过“流技术”把这个类的.java文件读取到“内存中的方法区”中变成“类.Class 文件”。

但是在Java中“万物皆对象”,于是类加载器又为这个Class文件创建了一个对象,这个对象被称为“Class文件的对象”,该对象所对应的类就是Class类(java.lang包下的Class类)。

Class类对象是反射技术的基石,由此引出反射。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值