1 //FileClassLoader为自定义的ClassLoader
2 public class FileClassLoader extends ClassLoader {
3 public static final String drive = "d:/";
4 public static final String fileType = ".class";
5 public FileClassLoader() {
6 super();
7 }
8 public FileClassLoader(ClassLoader arg0) {
9 super(arg0);
10 }
11 public Class< > findClass(String name) {
12 byte[] data = loadClassData(name);
13 return defineClass(name, data, 0, data.length);
14 }
15 public byte[] loadClassData(String name) {
16 FileInputStream fis = null;
17 byte[] data = null;
18 try {
19 fis = new FileInputStream(new File(drive + name + fileType));
20 ByteArrayOutputStream baos = new ByteArrayOutputStream();
21 int ch = 0;
22 //可以在这里完成读入后解密再回写的byte数组中的操作。
23 while ((ch = fis.read()) != -1)
24 baos.write(ch);
25 data = baos.toByteArray();
26 } catch (IOException e) {
27 e.printStackTrace();
28 }
29 return data;
30 }
31 }
32 //该测试类为将被FileClassLoader加载的class
33 public class MyApp {
34 private static int ii = 0;
35 static {
36 ii = 10;
37 System.out.println("Static block is initialized.");
38 }
39
40 public void print() {
41 System.out.println("ii = " + ii);
42 System.out.println("This is MyApp.print");
43 }
44 }
45 //以下代码为测试自定义ClassLoader调用的代码
46 public static void main(String[] args) throws Exception {
47 //如果将MyApp.class文件同时放到D:/根目录和应用程序当前的bin目录下时,
48 //会发现MyApp的类加载器不在是FileClassLoader,而是sun.misc.Launcher$AppClassLoader,
49 //因为AppClassLoader作为FileClassLoader的parent已经加载了该class,
50 //因此FileClassLoader将不会再重新加载该class。
51 FileClassLoader loader = new FileClassLoader();
52 Class< > objClass = loader.loadClass("MyApp");
53 System.out.println("Begin to getMethod");
54 Method m = objClass.getMethod("print");
55 System.out.println("Begin to newInstance.");
56 Object obj = objClass.newInstance();
57 System.out.println("Begin to invoke.");
58 m.invoke(obj);
59 System.out.println(objClass.getName());
60 System.out.println(objClass.getClassLoader());
61 }
62 /* 输出结果如下:
63 Begin to getMethod
64 Begin to newInstance.
65 Static block is initialized.
66 Begin to invoke.
67 ii = 10
68 This is MyApp.print
69 MyApp
70 FileClassLoader@1d7ad1c
71 */
复制代码
在介绍关于ClassLoader的最后,我们来讨论一下Class.forName("className")和loader.loadClass("className")两者之间的区别。
Class.forName()包含两个Overload的方法,我们经常使用的Class.forName(name)方法,在其实现的内部将会调用另一个Class.forName(name,initialize,loader)方法,其等同于Class.forName(name,true,CallClass.class.getClassLoader())的调用。这里的第二个参数表示装载类的时候是否初始化该类,即是否调用类的静态块的语句及初始化静态成员变量。而Class c = ClassLoader.loadClass(name)没有指定是否初始化的选项。因此在调用该方法时,被调用类的静态块代码不会被执行,静态变量也不会