1

我创建了简单的AppInfo库,它提供了一种简单的方法来显示有关 Java 应用程序中正在运行的软件版本的始终有效、自动更新的信息,这在与 CI 服务器的自动构建结合使用时特别有用。

在我的库中,有必要从 JAR(在桌面应用程序的情况下)读取 MANIFEST.MF,这是运行的最终应用程序(而不是从类路径上的任何其他应用程序)。目前,我使用基于 Sun 论坛中的一个想法的解决方案(该链接不再有效):

String classContainer = classFromRightJar.getProtectionDomain().getCodeSource().getLocation().toString();
URL manifestUrl = new URL("jar:" + classContainer + "!/META-INF/MANIFEST.MF");

它通常可以工作,但它会强制桌面应用程序的开发人员创建额外的 bean,该 bean 配置有位于特定 JAR 中的类的名称。

有没有更好的/通用的解决方案,它给出了 JAR 的名称/位置/MANIFEST.MF/来自运行桌面应用程序的 JAR?

感谢您的
帮助

4

2 回答 2

2

有一个系统属性“sun.java.command”,其中包含 jar 名称或类名称以及所有 main() 方法参数。所以对于调用

java -jar test.jar arg1 arg2

你会得到“test.jar arg1 arg2”和

java test.Test arg1 arg2

the property value would be "test.Test arg1 arg2". As the property's name would suggest, it's not "official" (does not have to work on non-Sun/Oracle implementations). I checked it on Java 7, don't know when it was introduced.

于 2012-02-11T10:41:20.917 回答
0

通过“强制桌面应用程序的开发人员创建额外的 bean...”,您的意思是您根本不希望他们必须引用任何应用程序的类名吗?如果是这样,那么可能没有任何 100% 可靠的方法来做到这一点,但一种方法可能是调用 java.awt.Frame.getFrames() 并检查 JFrame 的非 java* 子类。例如:

for (Frame frame in Frame.getFrames()) {
    if (frame.getClass().getPackage().getName().startsWith("java"))
        continue;
    URL manifestURL = frame.getClass().getResource("/META-INF/MANIFEST.MF");
    // do something with the manifest
}

如果应用程序不继承 JFrame/Frame 本身,这将崩溃,因此您可能还希望遍历框架的子级以检查子级的子类。

另一种方法可能是抓取 Thread.getAllStackTraces() 并遍历所有线程(尤其是“主”线程)以寻找启动应用程序的主类,然后抓取该类的清单。

不过,正如我所说,可能没有任何 100% 可靠的方法可以做到这一点,因为应用程序可能不使用任何自定义子类,并且线程的堆栈可能混合了不同的应用程序。

于 2010-11-07T00:21:59.137 回答