Java ClassLoader类加载器基础详解
作者:Tinyspot
这篇文章主要为大家介绍了Java ClassLoader类加载器基础详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
1. 类加载
- JVM 首次使用某个类时,需通过 ClassPath 查找该类的 .class 文件
- 将 .class 文件中对类的描述信息加载到内存中,进行保存
- 加载时机
- 创建对象
- 创建子类对象
- 访问静态属性
- 调用静态方法
- 主动加载:
Class.forName("full-name")
1.1 class 文件
包名、类名、父类、属性、方法、构造方法.....
2. 类加载器
- 在运行期间,如果我们要产生某个类的对象,JVM 会检测该类型的 Class 对象是否已被加载; 如果没有加载,JVM 会根据类的名称找到 .class 文件并加载它
- Class 对象代表 Java 应用程序在运行时所加载的类或接口实例,每加载一个类,
JVM自动生成一个Class对象
;
2.1 ClassLoader的分类
- Bootstrap ClassLoader 启动类加载器(引导类加载器)
- ExtClassLoader 扩展类加载器(Java9 之后改为 Platform Classloader)
- Application Classloader(系统类加载器或应用类加载器)
默认的类加载器
- 自定义类加载器,父类加载器为AppClassLoader
2.2 ClassLoader 层次结构
- 系统类加载器
--父-->
扩展类加载器--父-->
引导类加载器 - 除了引导类加载器之外,所有的类加载器都有一个父类加载器。 通过 getParent()方法可以得到
注意:父加载器不是父类
2.3 类与类加载器
- 在JVM中表示两个class对象是否为同一个类对象的两个必要条件
- 类的全限定名必须一致
- 加载这个类的ClassLoader必须相同
- 在JVM中,即使这个两个类对象(class对象)来源同一个Class文件,被同一个虚拟机所加载,但只要加载它们的ClassLoader实例对象不同,那么这两个类对象也是不相等的
2.3 获取 ClassLoader
@Test public void getClassLoader() { Class<?> clazz = String.class; ClassLoader classLoader = clazz.getClassLoader(); System.out.println(classLoader); // null, 根加载器并不是由Java语言实现的,因此拿不到根加载器对象 }
@Test public void getClassLoader2() throws ClassNotFoundException { // this.getClass().getClassLoader(); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); Class<?> clazz = classLoader.loadClass("com.example.concrete.common.domain.User"); System.out.println(classLoader); System.out.println(classLoader.getParent()); }
打印结果
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@51efea79
2.4 获得class对象的三种方法
方式一:对象.getClass()
String str = "hello"; Class<?> clazz = str.getClass();
方式二:类.classClass<?> clazz = String.class;
方式三:Class. forName() 动态加载类
// 静态方法 forName("类的全限定名") Class<?> clazz3 = Class.forName("java.lang.String");
3. ClassLoader 分析
loadClass(String name)
findClass(String name)
defineClass(String name, byte[] b, int off, int len)
// ClassLoader 的默认实现就是双亲委托 public abstract class ClassLoader { //每个类加载器都有个父加载器 private final ClassLoader parent; public Class<?> loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); } protected Class<?> findClass(String name) throws ClassNotFoundException { throw new ClassNotFoundException(name); } protected final Class<?> defineClass(String name, byte[] b, int off, int len) throws ClassFormatError { return defineClass(name, b, off, len, null); } }
name: 类的全限定名
public Class<?> loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); } /** * classpath 就是一组目录的集合;classpath 是 JVM 用到的一个环境变量,它用来指示 JVM 如何搜索class * 在启动 JVM 时设置 classpath 变量 * java -cp or java -classpath .;C:\work\project1\bin;C:\shared abc.xyz.Hello * 如果不设置,JVM 默认的 classpath 为. 即当前目录 */ String classpath = System.getProperty("java.class.path"); Properties properties = System.getProperties(); Set<String> strings = properties.stringPropertyNames(); for (String string : strings) { System.out.println(string); } /** * 若以“/”开头的,表示要从项目的 ClassPath 开始的( /mapper/xxx.xml ), * 如果前面没有这个“/”,那么表示的就是相对于该类的路径继续往下 */ URL resource = classLoader.getResource(""); // file:/.../target/classes/ URL resource1 = classLoader.getResource("bean.xml"); // file:/.../target/classes/bean.xml
4. Classpath
- lib 和 classes 同属 classpath,访问优先级为: lib > classes
- Java 项目 /src 目录下的文件(*.xml, *.properties)编译后会放到 WEB-INF/classes 目录,默认的 classpath 就是 WEB-INF/classes
- WEB-INF/ 是资源目录,客户端不能直接访问
- Maven 项目 resources 目录下的文件编译后在
BOOT-INF/classes
4.1 maven 项目 classpath 路径
Maven 项目目录
src |-- main |-- java |-- com.xxx |-- resources |-- application.yml
编译后目录
target |-- classes |-- com.xxx |-- application.yml
打包的 jar 解压后目录
|-- BOOT-INF |-- classes |-- com.xxx |-- application.yml |-- lib |-- org.springframework.boot.loader...
引用 classpath 路径下的文件,只需在文件名前加 classpath:
classpath:application-*.xml # 子目录 classpath:config/*.xml # **/ 表示任意目录 classpath:**/bean.xml
4.2 classpath vs classpath*
classpath
在当前classpath 中查找,只加载第一个 classpath 路径classpath*
不仅包含 class 路径, 还包括 jar 文件(classpath目录)classpath*
会从所有的classpath中加载文件
classpath:*.xml classpath*:config.xml
以上就是Java ClassLoader类加载器基础详解的详细内容,更多关于Java ClassLoader类加载器的资料请关注脚本之家其它相关文章!