Java ClassLoader - 缺少依赖项的NoClassDefFoundError

问题描述 投票:0回答:1

我正在尝试使用类加载器在运行时加载一个类。代码看起来大致如此:

URLClassLoader jarClassLoader =  new URLClassLoader(new URL[] { myIFile.getLocationURI().toURL() }); //myFile is a jar packaging required librairies
Class<? extends RTTestCase> testCaseClass = (Class<? extends RTTestCase>)jarClassLoader.loadClass("com.myPackagePath." + testCaseClassName);
RTTestCase myTestCase = testCaseClass.newInstance(); //java.lang.NoClassDefFoundError: org/eclipse/core/resources/IProject
jarClassLoader.close();

所以似乎jarClassLoader找不到IProject类。我在Eclipse中使用“export libraries”选项将我的类导出为jar,因此包含此类(一些eclipse库)的JAR在导出的JAR以及系统路径中都可用。

那我在这里错过了什么?是导出的JAR未正确打包的设置问题,还是需要先手动加载IProjects和所有其他依赖项?怎么做 ?

背景: 我正在构建一个从Eclipse环境启动的应用程序。此应用程序从当前工作空间和每个项目中查找其他项目,如果项目内容不正确或者大程序本身存在错误,则执行可能以难以分析的方式崩溃的大程序。 在执行大程序之前,我想以各种方式复制和修改Eclipse项目,以“转换”它。所以我希望有可能将这些转换规则与我的应用程序本身分开,让我的同事简单地实现从RTTestCase继承的类,编写他们想要对项目执行的任何操作,将其打包在jar中然后应用程序找到它,从jar中加载主类(标准化命名),可以通过将当前项目传递给类并运行main函数来执行转换。 其他解决方案,例如从命令行启动jar不是最佳的,因为项目可能必须再次加载,我们正在谈论技嘉大型项目(以及众多的执行)。此外,从应用程序加载转换规则将允许转换器提供例如配置GUI,或者直接从当前执行线程再次调用的评估挂钩。

java eclipse classloader
1个回答
0
投票

我想我有一个解决方案 - 部分至少......通过这种方式实例化ClassLoader:

URLClassLoader urlClassLoader = new URLClassLoader(new URL[] { testCaseFile.getLocationURI().toURL() }, Thread.currentThread().getContextClassLoader());

这使得当前线程ClassLoader(即我的应用程序的ClassLoader)成为新ClassLoader的父级。因此,当加载的类尝试使用类时,它首先在父类ClassLoader中搜索,该类可以访问整个Eclipse环境(因为我的应用程序是从Eclipse启动的)。

我说的是“部分”,因为如果我尝试在Eclipse之外执行应用程序,我可能会遇到问题,尽管应该可以将eclipse类路径作为参数传递。此外,我只进行了最低限度的测试(你好wolrd)。


更新:它工作......直到我决定从我加载的类中实例化新类,例如:

Class<? extends ParentClass> myClassA = urlClassLoader.loadClass(pathA);
Class<? extends ParentClass> myClassB = urlClassLoader.loadClass(pathB);

ParentClass myA = myClassA.newInstance(); //OK
ParentClass myB = myClassB.newInstance(); //OK
myA.methodThatInstantiatesClassB(); // NOK -> ClassDefNotFoundException

我想主线程Classloader不会被动态加载和实例化的类进一步继承......所以我开始搜索如何传递ClassLoader,或者更改系统ClassLoader,然后我才注意到,因为我从Eclipse,我可以将所有额外的JAR设置为我启动工具的项目的库,这样JAR就在系统ClassLoader中(我仍然需要动态地找到<?extends ParentClass>,但是我不知道不得不担心他们的依赖关系,因为一切都在他们的JAR中)。

我静态地这样做(在项目中配置构建路径),但我想也可以在文件夹中搜索JAR并在开始时将它们添加到System Classpath(例如ANT脚本)。


简而言之:

  • 在启动程序时,通过Eclipse配置或通过ANT /命令行将JARS添加到类路径
  • 动态加载“main”类(扩展程序已知的抽象父类)并在此之后正常使用它们。
© www.soinside.com 2019 - 2024. All rights reserved.