Java类加载器(Java Class Loader)是Java虚拟机(JVM)关键组成部分之一,作用是在运行时动态加载Java类并将类编译成字节码文件,然后交由JVM进行执行。
Java类加载器是Java运行时环境的核心组成部分,其作用包括:
-
将类文件转换为字节码。Java编程语言源代码需要编译成.class文件(字节码文件)才能被JVM解释执行。类加载器的作用就是将.class文件转换成JVM内部的二进制代码。
-
加载Java类。类加载器的主要作用是将字节码文件加载到JVM中。一般来说,类加载器会按照指定的顺序来查找类文件,如果找到就加载。如果找不到,会交给父类加载器,一直到顶层的引导类加载器找到为止。
-
管理Java类。类加载器还负责管理已经加载的类。当JVM不再需要某个类时,类加载器会负责卸载这个类,并释放该类占用的内存空间,以便系统可以更好地利用内存资源。
示例1:
//定义一个自定义类加载器
public class CustomClassLoader extends ClassLoader {
public CustomClassLoader() {
super(CustomClassLoader.class.getClassLoader());
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
byte[] bytes = "public class HelloWorld {public static void main(String[] args) {System.out.println(\"Hello,World!\");}}".getBytes();
return defineClass(name, bytes, 0, bytes.length);
}
}
//使用自定义类加载器加载 HelloWorld类
public class MyClassLoaderTest {
public static void main(String[] args) throws Exception {
CustomClassLoader classLoader = new CustomClassLoader();
Class<?> cls = classLoader.loadClass("HelloWorld");
Object obj = cls.newInstance(); //实例化
Method method = cls.getMethod("main", String[].class);
method.invoke(obj, (Object) new String[]{}) //调用main方法
}
}
示例2:
//定义一个自定义类加载器
public class CustomClassLoader extends ClassLoader {
public CustomClassLoader() {
super(CustomClassLoader.class.getClassLoader());
}
//重写findClass方法,通过读取指定路径下的文件,将文件内容转成class对象
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
String path = "E:/HelloWorld.class";
byte[] bytes = readClassBytes(path); //读取文件字节码
if (bytes == null) {
throw new ClassNotFoundException();
}
return defineClass(name, bytes, 0, bytes.length);
}
//读取指定路径下的文件字节码
private byte[] readClassBytes(String path) {
FileInputStream inputStream = null;
try {
File file = new File(path);
if (!file.exists()) {
return null;
}
inputStream = new FileInputStream(file);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
int len;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
return outputStream.toByteArray();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//使用自定义类加载器加载 HelloWorld类
public class MyClassLoaderTest {
public static void main(String[] args) throws Exception {
CustomClassLoader classLoader = new CustomClassLoader();
Class<?> cls = classLoader.loadClass("HelloWorld");
Object obj = cls.newInstance(); //实例化
Method method = cls.getMethod("main", String[].class);
method.invoke(obj, (Object) new String[]{}) //调用main方法
}
}
以上两个示例分别演示了通过自定义类加载器实现类文件转换为字节码,并通过字节数组将类文件加载到JVM内存中。自定义类加载器的加载顺序会先找自定义类加载器,如果找不到才交给父类加载器。