推荐链接:
总结——》【Java】
总结——》【JVM】
总结——》【Mysql】
总结——》【Spring】
总结——》【SpringBoot】
一、作用
在装载(Load)阶段,通过类的全限定名获取其定义的二进制字节流,需要借助类装载器完成,顾名思义,就是用来装载Class文件的。
二、分类
分类 | 功能 | 加载路径 | 加载范围 | 备注 |
---|---|---|---|---|
Bootsrap | 加载核心jar | $JAVA_HOME/jre/lib/rt.jar -Xbootclassspath指定目录下的jar | sun.boot.class.path | C++实现 |
Extension | 加载扩展jar | $JAVA_HOME/jre/lib/ext/*.jar -Djava.ext.dirs指定目录下的jar | java.ext.dirs | |
App | 加载指定jar | classpath指定jar -Djava.class.path指定目录下的jar和类 | java.class.path | |
Custom | 加载自定义class | 实现ClassLoader |
三、图解
四、示例
1、类加载器
Q:当String.class文件被加载到内存后,都做了什么?
A:在内存里创建了2块内容
(1)方法区:存储类的信息
(2)堆:生成了class类的对象,并指向了方法区里的内容
public class T002_ClassLoaderLevel {
public static void main(String[] args) {
// null,原因:底层是C++实现的,java没有类和它对应,所以返回null
System.out.println(String.class.getClassLoader());
// null
System.out.println(sun.awt.HKSCS.class.getClassLoader());
// sun.misc.Launcher$ExtClassLoader@45ee12a7 ,位于ext包下的类
System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader());
// sun.misc.Launcher$AppClassLoader@18b4aac2
System.out.println(T002_ClassLoaderLevel.class.getClassLoader());
// null
System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader().getClass().getClassLoader());
// null
System.out.println(T002_ClassLoaderLevel.class.getClassLoader().getClass().getClassLoader());
// sun.misc.Launcher$AppClassLoader@18b4aac2
System.out.println(new T006_MSBClassLoader().getParent());
// sun.misc.Launcher$AppClassLoader@18b4aac2,这是系统默认的classloader
System.out.println(ClassLoader.getSystemClassLoader());
}
}
2、父加载器
public class T004_ParentAndChild {
public static void main(String[] args) {
// sun.misc.Launcher$AppClassLoader@18b4aac2
System.out.println(T004_ParentAndChild.class.getClassLoader());
// null
System.out.println(T004_ParentAndChild.class.getClassLoader().getClass().getClassLoader());
// sun.misc.Launcher$ExtClassLoader@1540e19d
System.out.println(T004_ParentAndChild.class.getClassLoader().getParent());
// null
System.out.println(T004_ParentAndChild.class.getClassLoader().getParent().getParent());
// 报错 空指针
// System.out.println(T004_ParentAndChild.class.getClassLoader().getParent().getParent().getParent());
}
}
3、类加载器范围
public class T003_ClassLoaderScope {
public static void main(String[] args) {
String pathBoot = System.getProperty("sun.boot.class.path");
System.out.println(pathBoot.replaceAll(";", System.lineSeparator()));
System.out.println("--------------------");
String pathExt = System.getProperty("java.ext.dirs");
System.out.println(pathExt.replaceAll(";", System.lineSeparator()));
System.out.println("--------------------");
String pathApp = System.getProperty("java.class.path");
System.out.println(pathApp.replaceAll(";", System.lineSeparator()));
}
}
// 以下是运行结果
以下是sun.boot.class.path--------------------
D:\Java\jdk1.8.0_152\jre\lib\resources.jar
D:\Java\jdk1.8.0_152\jre\lib\rt.jar
D:\Java\jdk1.8.0_152\jre\lib\sunrsasign.jar
D:\Java\jdk1.8.0_152\jre\lib\jsse.jar
D:\Java\jdk1.8.0_152\jre\lib\jce.jar
D:\Java\jdk1.8.0_152\jre\lib\charsets.jar
D:\Java\jdk1.8.0_152\jre\lib\jfr.jar
D:\Java\jdk1.8.0_152\jre\classes
以下是java.ext.dirs--------------------
D:\Java\jdk1.8.0_152\jre\lib\ext
C:\Windows\Sun\Java\lib\ext
以下是java.class.path--------------------
D:\Java\jdk1.8.0_152\jre\lib\charsets.jar
D:\Java\jdk1.8.0_152\jre\lib\deploy.jar
D:\Java\jdk1.8.0_152\jre\lib\ext\access-bridge-64.jar
D:\Java\jdk1.8.0_152\jre\lib\ext\cldrdata.jar
D:\Java\jdk1.8.0_152\jre\lib\ext\dnsns.jar
D:\Java\jdk1.8.0_152\jre\lib\ext\jaccess.jar
D:\Java\jdk1.8.0_152\jre\lib\ext\jfxrt.jar
D:\Java\jdk1.8.0_152\jre\lib\ext\localedata.jar
D:\Java\jdk1.8.0_152\jre\lib\ext\nashorn.jar
D:\Java\jdk1.8.0_152\jre\lib\ext\sunec.jar
D:\Java\jdk1.8.0_152\jre\lib\ext\sunjce_provider.jar
D:\Java\jdk1.8.0_152\jre\lib\ext\sunmscapi.jar
D:\Java\jdk1.8.0_152\jre\lib\ext\sunpkcs11.jar
D:\Java\jdk1.8.0_152\jre\lib\ext\zipfs.jar
D:\Java\jdk1.8.0_152\jre\lib\javaws.jar
D:\Java\jdk1.8.0_152\jre\lib\jce.jar
D:\Java\jdk1.8.0_152\jre\lib\jfr.jar
D:\Java\jdk1.8.0_152\jre\lib\jfxswt.jar
D:\Java\jdk1.8.0_152\jre\lib\jsse.jar
D:\Java\jdk1.8.0_152\jre\lib\management-agent.jar
D:\Java\jdk1.8.0_152\jre\lib\plugin.jar
D:\Java\jdk1.8.0_152\jre\lib\resources.jar
D:\Java\jdk1.8.0_152\jre\lib\rt.jar
E:\IdeaProjects_mine\msb\JVM\out\production\JVM
D:\Program Files\JetBrains\IntelliJ IDEA 2021.2.1\lib\idea_rt.jar
4、加载指定类loadClass(path)
public class T005_LoadClassByHand {
public static void main(String[] args) throws ClassNotFoundException {
Class clazz = T005_LoadClassByHand.class.getClassLoader().loadClass("com.mashibing.jvm.c2_classloader.T002_ClassLoaderLevel");
System.out.println(clazz.getName());
//利用类加载器加载资源,参考坦克图片的加载
//T005_LoadClassByHand.class.getClassLoader().getResourceAsStream("");
}
}