介绍:
JVM是Java虚拟机的缩写,负责Java程序的编译、解释与运行。而Java程序在被JVM虚拟机执行前,需要被编译成字节码。在Java程序的运行中,JVM会使用ClassLoader来加载这些字节码,并将其转化为Java可执行的字节码。ClassLoader的作用就是用来加载类的,加载的类可以来自本地文件系统、JAR包、网络以及其他的上层数据源。本文将从ClassLoader的基本概念、ClassLoader的使用和自定义ClassLoader来详细讲解JVM类加载器之ClassLoader的使用。
一、ClassLoader的基本概念
ClassLoader的任务就是根据一个className将class文件加载到内存中。在Java中,ClassLoader有以下几个重要的属性和方法:
- ClassLoader是一个抽象类,定义了如下方法:
public abstract class ClassLoader{
public final ClassLoader getParent();
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException;
protected Class<?> findClass(String name) throws ClassNotFoundException;
}
其中,getParent()
方法用于获取当前ClassLoader的父ClassLoader,findClass()
方法用于查找类,loadClass()
方法用于加载类。
-
Bootstrap ClassLoader
Bootstrap ClassLoader是JVM启动时加载的最基本的ClassLoader,它主要是用来加载JDK自己的核心类库(system classes),比如rt.jar等,同时也是加载第三方JAR包中META-INF/services/java.sql.Driver中的实现类。 -
Extension ClassLoader
Extension ClassLoader用于加载JRE扩展目录中的Jar包中的类,其父ClassLoader为Bootstrap ClassLoader。 -
System ClassLoader
System ClassLoader也被称为Application ClassLoader,即用于加载应用程序classpath目录下的类,同时也可以加载-Djava.class.path指定路径下的类。
二、ClassLoader的使用
ClassLoader一般有以下使用方法:
-
ClassLoader.getSystemClassLoader()
方法获取系统ClassLoader,可以使用ClassLoader.getSystemClassLoader().loadClass("com.example.Test")
来加载Test类。 -
ClassLoader.getClassLoader()
方法获取当前线程的ClassLoader,比如Thread.currentThread().getContextClassLoader()
。 -
使用自定义ClassLoader,可以继承ClassLoader抽象类,实现
findClass()
方法来加载类。
下面是ClassLoader示例代码:
public class ClassLoaderDemo {
public static void main(String[] args) {
try {
//获取系统ClassLoader
ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
//加载类
Class testClass = systemLoader.loadClass("com.example.Test");
System.out.println("Loaded class: " + testClass.getName());
//获取当前线程的ClassLoader
ClassLoader currentLoader = Thread.currentThread().getContextClassLoader();
//加载类
Class testClass2 = currentLoader.loadClass("com.example.Test");
System.out.println("Loaded class: " + testClass2.getName());
//使用自定义ClassLoader加载类
ClassLoader customLoader = new CustomClassLoader();
Class testClass3 = customLoader.loadClass("com.example.Test");
System.out.println("Loaded class: " + testClass3.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
//自定义ClassLoader
class CustomClassLoader extends ClassLoader {
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
//从网络或其他位置获取类的二进制流
byte[] classBytes = getClassBytes(name);
//使用defineClass方法将二进制流转换成Class对象
return defineClass(name, classBytes, 0, classBytes.length);
}
//根据类名,从网络或其他位置获取类的二进制流
private byte[] getClassBytes(String name) {
//省略网络获取代码
return null;
}
}
三、自定义ClassLoader
如何使用自定义ClassLoader?
自定义ClassLoader主要有以下几个步骤:
-
继承ClassLoader抽象类
-
重写
findClass()
方法 -
通过
defineClass()
方法将二进制流转换成Class对象返回 -
使用自定义ClassLoader加载类
下面是一个基本的自定义ClassLoader示例:
class CustomClassLoader extends ClassLoader {
/**
* 根据类名查找类
*
* @param name 类名
* @return Class对象
* @throws ClassNotFoundException 查找不到对应的类时,抛出此异常
*/
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
String filePath = "/path/to/class/Student.class";
byte[] classBytes = getClassBytes(filePath);
if (classBytes == null) {
throw new ClassNotFoundException("Can't find class: " + name);
}
return defineClass(name, classBytes, 0, classBytes.length);
}
/**
* 从文件中获取字节码
*
* @param filePath class文件路径
* @return 返回字节码
*/
private byte[] getClassBytes(String filePath) {
// 省略实现
return null;
}
}
public class CustomClassLoaderDemo {
public static void main(String[] args) {
try {
ClassLoader customClassLoader = new CustomClassLoader();
Class clazz = customClassLoader.loadClass("com.example.Student");
System.out.println("Loaded class: " + clazz.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
以上就是JVM类加载器之ClassLoader的使用详解的完整攻略。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JVM类加载器之ClassLoader的使用详解 - Python技术站