我创建了一个简单的库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,这是从桌面应用程序运行的?
感谢您的帮助 马尔钦
答案 0 :(得分:2)
有一个系统属性“sun.java.command”,它包含jar名称或类名以及所有main()方法参数。所以对于调用
java -jar test.jar arg1 arg2
你会得到“test.jar arg1 arg2”和
java test.Test arg1 arg2
属性值为“test.Test arg1 arg2”。 正如该属性的名称所暗示的那样,它不是“官方的”(不必在非Sun / Oracle实现上工作)。我在Java 7上查了一下,不知道它何时推出。
答案 1 :(得分:0)
通过“强制桌面应用程序的开发人员创建其他bean ...”,您是否意味着您不希望他们根本不必引用任何应用程序的类名?如果是这样,那么可能没有任何100%可靠的方法,但一种方法可能是调用java.awt.Frame.getFrames()并检查JFrame的非java *子类。 E.g:
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%可靠的方法,因为应用程序可能不使用任何自定义子类,并且线程的堆栈可能混合使用不同的应用程序。