PaulLYang 2018-04-27 00:57 采纳率: 100%
浏览 1534
已采纳

关于Java自定义ClassLoader的类加载问题,求大神指点

本人自定义了一个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可以直接引用已经加载的类

  • 写回答

3条回答

  • 默默悟问 2018-04-27 01:33
    关注

    EffectiveJava在classLoaderOther,classLoaderOther里没有加载Animal和Dog(是加载在classLoader),所以报错。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥50 如何增强飞上天的树莓派的热点信号强度,以使得笔记本可以在地面实现远程桌面连接
  • ¥15 MCNP里如何定义多个源?
  • ¥20 双层网络上信息-疾病传播
  • ¥50 paddlepaddle pinn
  • ¥20 idea运行测试代码报错问题
  • ¥15 网络监控:网络故障告警通知
  • ¥15 django项目运行报编码错误
  • ¥15 请问这个是什么意思?
  • ¥15 STM32驱动继电器
  • ¥15 Windows server update services