本人自定义了一个Classloader,用于加载特定文件夹下面的class。
前期准备写了一个interface Animal,代码如下:
package com.paul.service;
public interface Animal {
public void jiao(String name);
}
有一个实现类 Dog, 代码如下:
package com.paul.impl;
import com.paul.service.Animal;
//Animal的实现类Dog
public class Dog implements Animal{
public void jiao(String name){
System.out.println("this is dog>>>>>>>>>>>>>"+name);
}
}
有一个测试类 EffectiveJava,里面有一个方面testClassLoader(String testStr), 代码如下:
package com.foxconn.paul.tool;
import com.paul.impl.Dog;
import com.paul.service.Animal;
public static void testClassLoader(String testStr){
Animal animal = new Dog();
animal.jiao(testStr);
}
自定义LoadClassFileClassLoader的核心代码:
public class LoadClassFileClassLoader extends ClassLoader{
private String clsssFilePath;
public LoadClassFileClassLoader(String clsssFilePath){
this.clsssFilePath = clsssFilePath;
}
private static String getClassFileName(String className){
StringBuilder sb = new StringBuilder();
className = className.substring(className.lastIndexOf(".")+1);
sb.append(className).append(".class").toString();
return sb.toString();
}
protected Class<?> findClass(String name) throws ClassNotFoundException {
System.out.println(" LoadClassFileClassLoader >>>>>>> overwrite findClass (String name)");
String fileName = getClassFileName(name);
File file = new File(clsssFilePath,fileName);
System.out.println(" class filePath >>>>> " + clsssFilePath + " fileName >>> " +fileName);
try {
FileInputStream is = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int len = 0;
while ((len = is.read()) != -1) {
bos.write(len);
}
byte[] data = bos.toByteArray();
is.close();
bos.close();
return defineClass(name,data,0,data.length);
} catch (IOException e) {
e.printStackTrace();
}
return super.findClass(name);
}
}
请注意这三个类都不在同一个package下。然后把编译好的Animal.class、Dog.class放入本地目录E:\classloader_test\; 把EffectiveJava.class放入本地目录E:\classloader_test\other\
测试时LoadClassFileClassLoader与Animal、Dog、EffectiveJava不在同一个工程里面。开始测试:
//加载Animal、Dog
LoadClassFileClassLoader classLoader = new LoadClassFileClassLoader("D:\\testClass\\");
Class<?> cInterfaceAnimal = classLoader.loadClass("com.paul.service.Animal");
Class<?> dog = classLoader.loadClass("com.paul.impl.Dog");
//加载EffectiveJava
LoadClassFileClassLoader classLoaderOther = new LoadClassFileClassLoader("E:\\classloader_test\\other\\");
Class<?> c = classLoaderOther.loadClass("com.foxconn.paul.tool.EffectiveJava");
if(c != null){
System.out.println(c);
Object obj = c.newInstance();
Method method = c.getDeclaredMethod("testClassLoader",String.class);
System.out.println(method.invoke(obj, "哈哈哈"));
}
运行程序报错,提示"java.io.FileNotFoundException: E:\classloader_test\other\Animal.class (系統找不到指定的檔案。)“
问题1. com.paul.service.Animal与com.paul.impl.Dog已经加载过了,为什么还要在加载com.foxconn.paul.tool.EffectiveJava时去加载Animal和Dog。这两个类为什么没在加载类的缓存里面?
问题2. 如果我要实现与加载java核心类库相同的效果。即我在前面已经加载过com.paul.service.Animal与com.paul.impl.Dog,那么我在com.foxconn.paul.tool.EffectiveJava可以直接引用已经加载的类