2016-09-19 63 views
0

我正在尝试使用自定义类加载器来加载随机.class文件,该文件可能位于文件系统的任何位置。我写了我的类加载器来扩展ClassLoader,覆盖了findClass()loadClass()方法,并读入类文件的字节流。产生的问题是在试图调用ClassLoader.defineClass()对于错误的目录结构,解决方法NoClassDefFoundError

确切的错误我得到的是当:

Exception in thread "main" java.lang.NoClassDefFoundError: Test (wrong name: com/foo/bar/Test) 
    at java.lang.ClassLoader.defineClass1(Native Method) 
    at java.lang.ClassLoader.defineClass(ClassLoader.java:800) 

我知道问题是本地类加载功能不喜欢的事实,Test.class不生活在/someDir/com/foo/bar/。有什么办法可以使这项工作?我的类加载器已经有代码来检查定义的类是否符合特定的包。我真的不明白为什么本地方法会拒绝这个(除了安全性,我不需要在这个用例中,然后事件,让我自己拍摄脚)。

+0

你是否在加载类的控制,因此可以修改它?如果是这样,是否需要包名?如果没有,只需不定义一个包名称,那么你应该能够从任何你想要的目录加载类。包名实际上是类的一部分,因此需要某些字节处理框架,如[Javassist](http://jboss-javassist.github.io/javassist/)加载字节,然后更新“类”表示通过类加载器实际加载。 –

+0

稍后,我将所有加载的类放在特定的包中,因此我依赖于特定的包名。但是,id喜欢将该类文件放置在目录结构中的任何位置,并仍然加载它。 – bss36504

+0

然后看看Javassit(或其他字节操纵框架) –

回答

1

本机类加载器,即ClassLoader.defineClass1,不知道关于目录结构的任何内容。它只是加载一个字节数组。

错误消息表明,作为参数传递给defineClass的二进制名称与从类数据字节中发现的实际名称不匹配。当调用defineClass时,最简单的解决方法是设置name=null

注意:您不能通过将其移动到不同的目录来更改类的包。包名称嵌入在类文件数据中。您必须使用正确的package指令重新编译源文件,或者在加载时使用字节码工具框架修改类文件字节。

+0

哇,我简直不敢相信那是简单的。这似乎工作,非常感谢你! – bss36504