包装罐子时会导致“找不到主要类”的原因是什么?

时间:2011-11-03 08:21:05

标签: java ant jar main

我正在参与一个开源项目,在那里我有自己的回购用于我正在进行的修改。

我在过去几个月里添加了新功能,同时始终在eclipse中测试功能。现在一切准备就绪,我想发布一个版本,使用ant脚本构建Windows安装程序,该脚本始终生成一个正常工作的安装程序,但在安装后,启动应用程序时,会立即显示带有此消息的信息窗口。

Java虚拟机启动器 找不到主类:net.pms.PMS。程序将会退出。 行

我无法弄清楚打破包装有什么变化。

一些事实:

  • 要构建安装程序,ANT script正在调用两个NSIS scipts 用过的。这是包装jar的ANT脚本。这两个版本之间的脚本没有变化。 main方法的清单(net.pms.PMS)正在ANT脚本中设置。
  • 两个版本之间有相当多的代码发生了变化;因为在启动应用程序时会立即显示主要类未找到错误我倾向于认为改变的代码和更改的jar导入都不会引起错误!?
  • 包含主类的类文件包含在包中,我保证PMS.java包含一个主方法pms-mlx jar content
  • 应用程序的启动方式无关紧要; exe启动器,batch file或命令行,找不到主类。
  • 我安装了jdk7。因为它可能与jdk6冲突,我已经卸载了与7相关的所有内容并且当前运行的是jdk6_29
  • 应用程序中提供了一个插件系统,其中插件在运行时ExternalFactory上动态地从文件夹加载。这样做的方式已经发生了很大变化。再次,就像在运行时一样,我无法想象那里的某些东西会引发问题。
  • 我在Windows事件日志中找不到任何信息,没有找到任何java日志,显然应用程序日志根本没有初始化。

我目前一无所知我所做的改变引起了这个主要类没有找到错误。如果有人可以通过一些线索向我指出正确的方向,我可以从中获得一些有用的信息或实际发生的事情,我将非常感激。

谢谢,Philippe

[edit]与发布的评论相关的一些补充:

MANIFEST.MF的内容:
清单 - 版本:1.0
Ant-Version:Apache Ant 1.8.2
创建者:1.6.0_29-b11(Sun Microsystems Inc.)
主类:net.pms.PMS

申请如何开始:
如果使用批处理启动:javaw -Xmx768M -Djava.net.preferIPv4Stack = true -Dfile.encoding = UTF-8 -classpath update.jar; pms.jar net.pms.PMS
使用NSIS生成的exe:-classpath update.jar; pms.jar -Xmx1024M -Dsun.java2d.d3d = false -Djava.net.preferIPv4Stack = true -Dfile.encoding = UTF-8 $ {CLASS} $ 1
< / p>

尝试使用'java -cp pms.jar net.pms.PMS'启动时,会出现一个有问题的堆栈跟踪 C:\Program Files (x86)\PS3 Media Server MLX>java -cp pms.jar net.pms.PMS Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes at sun.security.util.SignatureFileVerifier.processImpl(Unknown Source) at sun.security.util.SignatureFileVerifier.process(Unknown Source) at java.util.jar.JarVerifier.processEntry(Unknown Source) at java.util.jar.JarVerifier.update(Unknown Source) at java.util.jar.JarFile.initializeVerifier(Unknown Source) at java.util.jar.JarFile.getInputStream(Unknown Source) at sun.misc.JarIndex.getJarIndex(Unknown Source) at sun.misc.URLClassPath$JarLoader$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at sun.misc.URLClassPath$JarLoader.ensureOpen(Unknown Source) at sun.misc.URLClassPath$JarLoader.(Unknown Source) at sun.misc.URLClassPath$3.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at sun.misc.URLClassPath.getLoader(Unknown Source) at sun.misc.URLClassPath.getLoader(Unknown Source) at sun.misc.URLClassPath.getResource(Unknown Source) at java.net.URLClassLoader$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) Could not find the main class: net.pms.PMS. Program will exit.

4 个答案:

答案 0 :(得分:3)

好的,我将引导您完成我分析问题的过程:

  • 我拿了你的jar并尝试通过java -jar pms.jar运行它。实际上,上述错误消息失败了。
  • 我在你的包中创建了一个快速测试类,它只是将一条消息打印到system.out并将其放在文件夹net.pms中的jar文件中。
  • 我手动更改了Manifest中的Main-Class属性来调用该类(因此:net.pms.Test)。
  • 我重新运行java -jar pms.jar并收到相同的错误消息。
  • 我从jar的根目录中删除了所有其他文件夹,然后重新运行java -jar pms.jar。它产生了相同的错误消息。
  • 我从META-INF删除了所有其他文件夹并重新运行java -jar pms.jar。它仍然会产生相同的错误消息。
  • 我从META-INF删除了所有其他文件并重新运行java -jar pms.jar。该应用程序运行良好。
  • 我开始使用jar的新副本,仅删除META-INF中的所有其他文件并重新运行java -jar pms.jar。该应用程序运行良好。
  • 我开始使用jar的新副本,然后逐个删除META-INF中的其他文件,重新运行java -jar pms.jar。这给了我以下结果:

如果您的META-INF目录包含文件NB_IDE.DSANB_IDE.SF中的任何一个,则Java无法找到您的应用程序的主类。看来这些文件中的信息会以某种方式影响类加载器的位置机制。

我查看了文件,似乎是一些Netbeans特定的信息文件。 Google并没有真正给我任何结果,我的同事网络也没有任何线索。此时,我通常会向StackOverflow寻求帮助,但是看到文件只涉及Netbeans依赖关系信息,我假设这些文件仅在IDE中使用。此外,由于这是构建时需要的信息,而不是在运行时,我认为从最终版本jar中删除文件是安全的。

您现在要做的就是通过build.xml排除最终版本中的文件。我会把这个留给你,因为互联网上有很多关于Ant的文档。 :)

现在,为什么我要详细介绍这一点?
嗯,如果我遇到这样的问题,这是我遵循的典型过程。首先,我排除所有干扰参数以查明问题。然后,我分析结果 - 可能使用互联网澄清我不熟悉的要点 - 不解决症状而是原因。然后我消除了原因。

就我个人而言,我认为这个过程是每个开发人员工具箱中的一个很好的工具,可以快速解决您所面临的问题。我希望你可以在将来的某个时候重复使用它,而不必等待几天和几天让我的懒人最终看看它。 :)

祝你的软件好运!

答案 1 :(得分:0)

您以前是否曾经使用过构建的包?在同一台机器上?你是从命令行运行它还是尝试?

您目前是否通过双击运行它?我想我们假设你在Windows中,因为你使用的是WinRAR。

你正专注于所谓的“改变......打破包装”;您是否确定您的环境已正确设置以运行该程序?您没有列出必要的库,目录等详细信息。

您告诉我们该类位于jar文件中,但您没有告诉我们它在哪个路径上。我同意清单会很有用。

如果我们真的在查看蚂蚁问题,您可以为Ant标记此问题。

答案 2 :(得分:0)

嗯,首先,我假设MANIFEST.MF位于META-INF文件夹中 - 否则您可能很久以前就已经通过谷歌找到了解决方案。 :)

你说的是你保证PMS.java包含一个主类[sic]。 除非你在那里写了一个拼写错误并且你实际上意味着主要的'方法',我想你有一个内部类,你想作为你的应用程序的主要入口点。你帖子中的jar结构为我们提供了进一步的证据,因为它告诉我们你的主类确实有多个内部类。

我必须说,通过内部类启动应用程序是一个非常奇怪的构造,坦率地说,我不确定这是否可能。我强烈建议你直接将main方法移到PMS.java中。

如果您确实想要使用内部类作为入口点,请尝试使用此类内容作为清单中的Main-Class属性:

Main-Class: net.pms.PMS$1

其中$1是实际包含main方法的类。

同样,因为我不知道你的内部类是否需要外部类的实例以及Java是否实际上支持内部类作为应用程序的起点,所以这可能根本不起作用。我的建议仍然是将主要方法移到PMS.java中。

祝你好运!

答案 3 :(得分:0)

好吧,我想我知道可能会发生什么:你用来运行应用程序的命令确实把你的jar文件放在了类路径上,但它们并没有告诉Java在哪里找到主类!

javaw -Xmx768M -Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8 -classpath update.jar;pms.jar net.pms.PMS

这告诉Java在类路径中使用pms.jar并转到当前结构中的文件夹net/pms以运行类PMS

试试简单:

java -jar pms.jar

正如AlexR所建议的那样,请告诉我们这些内容......