jvm中类加载器分类

类加载器是分级的,自上而下是:

  • BootstrapClassLoader 启动类加载器,加载java_home/jre/lib下的类,由c++编写,不能通过java程序直接获取。
  • ExtensionClassLoader 扩展类加载器,加载java_home/jre/lib/ext下的类。
  • ApplicationClassLoader 应用程序类加载器,加载classpath下的类。
  • 自定义类加载器 加载自义定路径下的类。

当加载一个类时,先询问直接上级类加载器,是否加载过这个类,如果加载过那么类加载器不再加载,如果该上级加载这个类那么上级类加载器会加载。比如加载一个string类,应用程序类加载器询问扩展类加载器,是否加载过该类,扩展类加载器再询问启动类加载器,启动类加载加载了string类,其他类加载器不再加载。比如当加载一个自定义类Student类,应用程序类加载器询问扩展类加载器是否加载过该类,扩展类加载器询问启动类加载器是否加载过该类,启动类加载器回复未加载,扩展类加载器回复未加载,应用程序类加载器进行Student类的加载。

启动类加载器: 

package com.tech.load.loader;

/**
 * @author lw
 * @since 2021/12/1
 */
public class F {
    static {
        System.out.println("bootstrap F init");
    }
}
package com.tech.load.loader;

/**
 * 用Bootstrap类加载器加载类
 * @author lw
 * @since 2021/12/1
 */
public class Load5_1 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> aClass = Class.forName("com.tech.load.loader.F");
        System.out.println(aClass.getClassLoader());
    }
}

由于采用Class.forName获取F类的类型对象,会触发F类的初始化,调用类的构造方法Cinit执行F类的静态程序块。

测试启动类加载器,启动类加载器加载java_home/jre/lib目录下的类,也就是核心类,为了测试启动类加载器,我们需要把F类的类路径添加到核心类的路径下运行

先进行编译进入target/classes目录下执行

D:\Tech\code\tech-jvm\target\classes>java -Xbootclasspath/a:. com.tech.load.loader.Load5_1
bootstrap F init
null

bootclasspath:可以替换核心类:

  • java -Xbootclasspath:<newbootclasspath> 替换新的核心类路径
  • java -Xbootclasspath/a:<追加路径> 在原核心类路径后面追加新的核心类路径
  • java -Xbootclasspath/p:<追加路径> 在原核心类路径前面追加新的核心类路径

可以看到执行后,静态代码块内容被打印,说明类已经被加载并完成了初始化,类加载器为null说明采用的是启动类加载器加载的类,因为F类的路径被添加到了核心类路径中,核心类由启动类加载器负责加载。

扩展类加载器及应用程序类加载器

package com.tech.load.loader;

/**
 * @author lw
 * @since 2021/12/1
 */
public class G {
    static {
        System.out.println("classpath in G");
    }
}

 

package com.tech.load.loader;

/**
 * 用External类加载器加载类
 * @author lw
 * @since 2021/12/1
 */
public class Load5_2 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> aClass = Class.forName("com.tech.load.loader.G");
        System.out.println(aClass.getClassLoader());
    }
}

运行

classpath in G
sun.misc.Launcher$AppClassLoader@18b4aac2

采用的是应用程序类加载器

创建一个与G同名的类,内容如下

package com.tech.load.loader;

/**
 * @author lw
 * @since 2021/12/1
 */
public class G {
    static {
        System.out.println("ext in G");
    }
}

将G打成jar,添加到java_home/jre/lib/ext目录下

D:\Tech\code\tech-jvm\target\classes>jar -cvf my.jar com/tech/load/loader/G.class
已添加清单
正在添加: com/tech/load/loader/G.class(输入 = 477) (输出 = 317)(压缩了 33%)

 

 继续运行Load5_2 输出如下信息:

 

说明使用的类加载器为扩展类加载器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值