Java ClassLoader - 缺少依赖项

时间:2017-12-15 09:03:38

标签: java eclipse classloader

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

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类。我确实使用&#34;导出库&#34;将我的类导出为jar。 Eclipse中的选项,因此包含此类(某些eclipse库)的JAR在导出的JAR和系统路径中都可用。

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

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

1 个答案:

答案 0 :(得分:0)

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

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

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

我说&#34;部分&#34;因为如果我尝试在Eclipse之外执行应用程序,我可能会遇到问题,尽管应该可以将eclipse类路径作为参数传递。此外,我只进行了最低限度的测试(hello 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,然后我才注意到,因为我&#39;从Eclipse开始我的工具,我可以将所有额外的JAR设置为我启动工具的项目的库,以便JAR在系统ClassLoader中(我仍然需要动态地找到&lt;?extends ParentClass&gt;但是我不必担心他们的依赖关系,因为一切都在他们的JAR中。)

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

简而言之:

  • 在启动程序时,通过Eclispse配置或通过ANT /命令行将JARS添加到类路径

  • 动态加载&#34; main&#34; class(扩展程序已知的抽象父类)并在此之后正常使用它们。