【问题标题】:Workaround NoClassDefFoundError for wrong directory structure错误目录结构的解决方法 NoClassDefFoundError
【发布时间】:2017-01-27 15:08:51
【问题描述】:

我正在尝试使用自定义类加载器来加载可能位于文件系统上任何位置的随机 .class 文件。我编写了类加载器来扩展ClassLoader,覆盖findClass()loadClass() 方法,并读入类文件的字节流。尝试调用ClassLoader.defineClass() 时会出现问题

我得到的确切错误是:

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/ 中的事实。有什么办法可以使这项工作?我的类加载器已经有代码来检查定义的类是否符合特定的包。我真的不明白为什么本机方法会不允许这样做(除了安全性,我在这个用例中不需要,然后事件,让我在脚上开枪)。

【问题讨论】:

  • 您是否控制要加载的类并因此可以修改它?如果是这样,是否需要包名称?如果没有,只需不定义包名称,那么您应该能够从您想要的任何目录加载该类。包名实际上是类的一部分,因此需要某些字节操作框架(如Javassist)来加载字节,然后在通过类加载器实际加载之前更新“类”表示。
  • 稍后我在一个特定的包中找到所有加载的类,所以我依赖包名是特定的。但是,id 喜欢将该类文件放在目录结构中我想要的任何位置并仍然加载它。
  • 然后看看Javassit(或其他字节操作框架)

标签: java classloader


【解决方案1】:

本机类加载器,即ClassLoader.defineClass1,对目录结构一无所知。它只是加载一个字节数组。

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

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

【讨论】:

  • 哇,我不敢相信事情就这么简单。这似乎奏效了,非常感谢!
猜你喜欢
  • 2021-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
  • 1970-01-01
  • 2023-02-10
  • 1970-01-01
相关资源
最近更新 更多