# 4.1 ClassLoader API
ClassLoader是一个抽象类,不能直接使用,因此我们需要继承并重写其中的方法。它的主要方法有defineClass、loadClass、findClass和resolveClass等及其重载方法。主要方法的定义如下:
// 方法的输入是字节码的byte数组,输出是Class对象,它的作用是将字节码数组解析为Class对象
protected final Class<?> defineClass(String name, byte[] b, int off, int len)
// 通过类名称查找Class对象
public Class<?> loadClass(String name)
// 通过类名称查找类
protected Class<?> findClass(String name)
// 类加载后调用该方法完成类的链接
protected final void resolveClass(Class<?> c)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
先来实现一个简单的类加载器NetworkClassLoader,这个类加载器具备从网络加载类文件的能力, 实现代码如下。
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
public class NetworkClassLoader extends ClassLoader {
// 下载地址
private String downloadUrl;
public NetworkClassLoader(String downloadUrl) {
this.downloadUrl = downloadUrl;
}
// 实现类的查找方法
@Override
public Class findClass(String name) {
byte[] b = loadClassData(name);
return defineClass(name, b, 0, b.length);
}
// 从远程下载类文件,从而获得类的字节码数组
private byte[] loadClassData(String name) {
// load the class data from the connection
// ...
}
// 类名称转化为服务器下载的地址
private String classNameToPath(String name) {
return downloadUrl + "/" + name.replace(".", "/") + ".class";
}
// 测试方法
public class Main {
public static void main(String[] args) throws Exception {
// 下载地址
String baseUrl = "https://wwww.jrasp.com";
// 初始化网络类加载器
NetworkClassLoader loader = new NetworkClassLoader(baseUrl);
// 加载位于 https://wwww.jrasp.com/Foo.class的类,并创建实例
Object foo = loader.loadClass("Foo").newInstance();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
被加载的类Foo是一个简单类,在创建实例对象时输出"create new instance",Foo类的代码如下。
public class Foo {
public Foo() {
System.out.println("create new instance");
}
}
// 运行Main方法,输出结果如下:
// create new instance
1
2
3
4
5
6
7
2
3
4
5
6
7
ClassLoader主要功能是类查找、加载和链接等过程, 除了加载类之外,类加载器还负责加载资源如配置文件或图片等。