【问题标题】:Eclipse Java application dynamically importing JARs from another applicationEclipse Java 应用程序从另一个应用程序动态导入 JAR
【发布时间】:2014-08-01 06:25:50
【问题描述】:

我有 2 个 Java 应用程序需要能够相互通信 - 如果第二个已安装。两个应用程序/框架都很广泛,核心代码不在我的控制之下,但我可以扩展我需要使用的部分,我只是无法重写已经存在的部分。

我的第一个应用程序是一组基于 Eclipse 的插件。我需要从这里连接到第二个应用程序以从中提取数据。

我的第二个应用程序是基于客户端-服务器的应用程序,如果客户端应用程序安装在同一台机器上,我需要能够创建到服务器的无头连接(代替客户端)。在我的开发环境中有适合执行此操作的 Java API,但它们可能部署在也可能不部署在用户的机器上。

我不能将第二个应用程序的 JAR 打包并与第一个应用程序一起交付,因为这绝对会侵犯版权等。所以我需要能够允许第一个应用程序的用户指定安装目录对于第二个应用程序(如果他们已安装)。

我希望能够做的是让第一个应用程序的用户指定第二个应用程序的安装目录,并从该位置加载我需要的任何类,而无需进行太多微配置。

编辑:到目前为止我所做的是创建了 2 个 OSGI 插件。第一个允许第一个应用程序的用户指定第二个应用程序的工作目录。如果设置了此路径,那么我将尝试使用反射来加载第二个插件,该插件引用了第二个应用程序所需的类。但是试图反映这个类 - 我似乎无法在类路径等中找到它。我尝试的是

Class<?> c = Class.forName("com.package.impl.Activator");

ClassLoader classloader = Thread.currentThread().getContextClassLoader();                   
Class<?> c = classloader.loadClass("com.package.impl.Activator")

我还尝试通过使用查看 Classpath 中的其他类来尝试和帮助

ImmutableSet<ClassPath.ClassInfo> paths = ClassPath.from(Thread.currentThread().getContextClassLoader()).getAllClasses();

但这并没有返回任何预期的插件类,并且只包含框架类,例如

com.sun.crypto.provider.AESCipher
com.sun.crypto.provider.TlsRsaPremasterSecretGenerator
com.sun.crypto.provider.ai
com.sun.java.accessibility.AccessBridge
com.sun.java.accessibility._AccessibleState
com.sun.java.accessibility.util.AWTEventMonitor
com.sun.java.accessibility.util.java.awt.ButtonTranslator
com.sun.java.accessibility.util.java.awt.TextComponentTranslator
etc...

我不确定在设置类路径、使用反射找到我的插件类方面缺少什么。有什么想法吗?

PS 这两个应用程序都在 Windows 桌面上运行。

【问题讨论】:

    标签: java eclipse eclipse-plugin osgi classpath


    【解决方案1】:

    我会说以您尝试的方式动态加载类是一个死胡同。我看到两个选项:

    如果 client APIsbundle jar 中交付(意思是:它可以作为 bundle 加载到您的 OSGi 框架中),解决方案是加载客户端使用标准 OSGi API BundleContextBundleBundleContext.installBundleBundle.start)的第一个插件的 API 包。这应该是可能的,因为您在用户输入安装位置后知道客户端 API jar 的位置。之后,您可以对依赖于这些客户端 API 的第二个捆绑包执行相同的操作。这应该会调出执行该功能的所有软件。

    如果客户端 API 以普通 jar 的形式提供并且您无法说服供应商为您创建捆绑 jar,情况会稍微复杂一些。首选的解决方案是将客户端 API jar 动态包装到捆绑 jar 中。周围已经有执行此操作的软件(bnd、pax、eclipse、各种框架)。包装后,您又回到了第一个解决方案。但问题是,考虑到许可条款,这是否会被允许。

    如果以上所有方法都失败了,我想没有其他解决方案可以在插件环境之外创建软件,通过某种 RPC 解决方案弥合差距:您需要编写一些使用客户端 jar 的非插件代码。这部分在自己的 JVM 中运行,并通过远程方法调用与您的 OSGi 框架中的插件进行通信。

    希望这会有所帮助,或者这个答案会引起一些后续跟进,并提供更好的解决方案。

    【讨论】:

    • 我可以补充一点,如果客户端 API 包是通过 P2 提供的,您可以从 P2 存储库安装包及其所有依赖项,或多或少单个P2 API 调用。否则,通过 BundleContext API 安装可能会非常复杂(且脆弱)。
    • 阿里,谢谢。客户端 API 肯定没有捆绑。我试图找出提供者是否可以做到这一点,但到目前为止还没有运气。第二个选项,我使用 eclipse 进行了探索,理论上可行,但有很多问题,如果我打包所有 300 个 JAR,性能很糟糕(解包 JAR 时服务器连接时间从 8 秒跳到 2.5 分钟)。如果我试图只打包我需要的东西,我会不断地运行难以追踪的缺失依赖项。创建一个单独的程序可能就是答案。
    • @IlyaShinkarenko 虽然有些 API 是通用的,但很大一部分是由提供者专门编写的,仅供此应用程序使用。
    • 您可以创建一个包含所有需要的依赖项的 P2 存储库,并使用 P2 API 一次下载并安装所有依赖项。
    • @IlyaShinkarenko - 我无法创建 P2 存储库,这些不是我的 JAR。 API 将由第 3 方安装供我使用,或者它们将不存在并且我的功能将无法运行。我无法提供第 3 方 API 来使我的功能正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多