为什么我的JAR文件可以在命令行中执行,但双击无法运行?

21

我正在编写一个简单的3D GUI应用程序,希望用户只需双击JAR文件即可使用。在将其放入JAR文件之前,我已经完美地让它工作了,并且在从命令提示符运行时也可以完美地在JAR文件中工作(在JAR文件目录中键入“java -jar Modeler.jar”)。但是,当我双击它时,什么都不会发生。在命令提示符上正常运行,没有错误。我知道从经验上讲,启动时的崩溃报告不会显示,因为控制台未出现(或者消失得太快),但是从命令提示符运行时没有崩溃报告。有任何想法为什么它不能工作吗?我正在运行Windows 7 Home Premium。如果有帮助,以下是JAR文件的内容:

Modeler.jar
|
+--*all the class files necessary*
|
+--META-INF
   |
   +--MANIFEST.MF

MANIFEST.MF的内容:

Manifest-Version: 1.0
Built-By: AnonymousJohn
Class-Path: bin/j3dcore.jar bin/j3dutils.jar bin/vecmath.jar
Created-By: 1.6.0_16 (Sun Microsystems Inc.)
Main-Class: Start

编辑:在尝试更改文件关联使用java.exe而不是javaw.exe(从而提供了一个窗口进行打印输出),然后稍微修改启动机制以打印出当前工作目录之后,我发现jar正在从“C:\Windows\system32”运行,而不是我放置它的桌面文件夹中。无论如何,将必要的外部文件移动到那里都没有帮助。

编辑2:我尝试创建另一个JAR文件,这次它包含一个简单的JFrame和一个其中有按钮告诉你当前的工作目录。按下按钮会打开一个(无用的)JFileChooser。无论我把它放在电脑上的哪个位置,它都可以双击打开。所以我的JAR文件肯定有问题。我将再次开始排除错误。

编辑3:问题就像我想的那样:当我双击它时,它无法正确加载库。奇怪的是,在我显示当前路径和库路径的测试中,无论是通过命令提示符还是双击运行,输出都完全相同。以下是堆栈跟踪:

java.lang.UnsatisfiedLinkError: no j3dcore-d3d in java.library.path
  at java.lang.ClassLoader.loadLibrary(Unknown Source)
  at java.lang.Runtime.loadLibrary0(Unknown Source)
  at java.lang.System.loadLibrary(Unknown Source)
  at javax.media.j3d.NativePipeline$1.run(NativePipeline.java:231)
  at java.security.AccessController.doPrivileged(Native Method)
  at javax.media.j3d.NativePipeline.loadLibrary(NativePipeline.java:200)
  at javax.media.j3d.NativePipeline.loadLibraries(NativePipeline.java:157)
  at javax.media.j3d.MasterControl.loadLibraries(MasterControl.java:987)
  at javax.media.j3d.VirtualUniverse<clinit>(VirtualUniverse.java:299)
  at javax.media.j3d.Canvas3D.<clinit>(Canvas3D.java:3881)
  at ModelPreview.<init>(ModelPreview.java:51)
  at Modeler.<init>(Modeler.java:76)
  at Modeler.main(Modeler.java:1227)
  at Start.main(Start.java:92)

唯一的问题是它在库路径中。我特别将其设置在程序中。现在我认为这可能是问题所在。我是这样设置的(这是我在互联网上找到的一个方法,我不记得在哪里找到的):

//above was code to get newPath based on the Operating System.
//all this code is set in a try-catch phrase.
//reset the library path
System.setProperty("java.library.path", ".\\bin\\natives" + newPath + ";");
//make sure the ClassLoader rereads the NEW path.
Field f = ClassLoader.class.getDeclaredField("sys_paths");
f.setAccessible( true );
f.set(null, null); //ClassLoader will automatically reread the path when it sees that it is null.  

编辑最终结果:好吧,在查看和反复检查我的代码后,我发现问题在于一些关于检测64位系统的无聊操作,导致它加载了错误的dll文件。为什么它可以通过命令行工作而不能通过双击运行,我不知道,也可能永远不会知道,但是现在通过双击可以运行了,所以我很高兴。抱歉给您带来麻烦。


“Start”是您要运行的类的名称吗?它是否在默认(无)包中? - Andy White
是的,“Start”是我要运行的类的名称(它设置了环境),而且它确实在默认包中。我曾经试图让打包工作起来,但它并没有成功,所以我把所有东西都留在了默认包中。 - AnonymousJohn
可能是 https://dev59.com/OXRC5IYBdhLWcg3wJNqf 的重复问题。 - Ted Hopp
哎呀,看来我错过了那个。我会尝试那个解决方案并回来更新的。 - AnonymousJohn
那个解决方案没有帮助。它仍然无法启动。我再次检查了CMD,它仍然可以从那里工作。 - AnonymousJohn
注意:在Java中设置java.library.path是无用的。此属性只应在JVM实例化期间设置。然后它可以更改,但新值会被忽略。 - Rekin
7个回答

29

好的,我在过去一周里为这个具体问题被卡住了(因为这是一个副业项目,我每天只能抽出几个小时来做)。

这个问题发生在我的台式电脑上,但出于某种原因,在笔记本电脑上没有出现这个问题。

在寻找解决方案后,我找到了这个答案,我想与那些和我一样,在接受的答案中找不到任何有用信息的人分享。鸣谢匿名的 Stack Overflow 用户,我已经在所有的兴奋中失去了他的用户名。

正如其他一些答案所提到的,似乎与此问题无关,请使用这个小程序将您的 JAR 文件与 64 位版本的 java 相关联:

http://johann.loefflmann.net/en/software/jarfix/index.html

将该程序保存在某个地方,并在命令行中使用参数 /64 运行它: c://path//jarfix.exe /64

除此之外,没有别的方法适用于我,但这就像魔法一样。 :)


谢谢Eric。你救了我的一天 :) - sappu
谢谢。我现在可以睡觉了!:D - Felipe Carminati
您,先生,是一个传奇。我差点要把我的头发都拔光了。 - user3900751
谢谢,这对我也有用。但是我的可执行JAR文件仍然显示为JAR文件。我也想解决这个问题。 - vv88
这个?https://dev59.com/EGDVa4cB1Zd3GeqPcl6- - Ari Black

8

JAR文件可以通过CMD执行。这意味着JAR文件本身被正确地构建了。很好。

现在失败的唯一原因是双击没有产生正确的命令。如你所说,期望的命令是

java -jar Modeler.jar

但是当你将javaw.exe与JAR扩展名相关联时,我猜它会执行。
javaw Modeler.jar

很容易检查:创建一个名为javajar.cmd的文件,其中包含以下内容。
javaw -jar %*

将其与JAR相关联。如果您的应用程序可以正常启动,那么我是正确的。否则,很抱歉。


实际上我注意到文件关联是"javaw.exe -jar "%1" %*"(我没有在javaw之前包括路径)。我不认为删除%1会有帮助,但我可以尝试。编辑::毫无效果。:/ 那也没用。 - AnonymousJohn
重新阅读了您的回复后,我意识到您说要将命令放入批处理文件中,所以我这样做了。我所做的关联是这样的:' "C:\test.bat" %* '。奇怪的是,当批处理文件运行时,该命令的输出(我没有关闭回显)是这样的:"javaw -jar"。显然,我要么使用了错误的关联,要么Windows没有像应该一样传递参数。 - AnonymousJohn
尝试使用%1以确保。虽然%*应该可以工作。(我在Linux上,无法测试) - Vladimir Dyuzhev
我刚想到这个并尝试了一下,但也不起作用。最奇怪的是我可以运行其他JAR文件。我将编译一个简单的测试GUI JAR文件,看看是否可以运行。可能是因为它需要外部文件(它在j3d jars上运行,我将其保存在JAR旁边的文件夹中)。 - AnonymousJohn

2

我厌倦了在Windows 7控制面板中无法修改文件关联,于是我编辑了注册表(注意:如果你认为有任何可能会出错,请务必设置还原点,这并不是一个坏主意)(我既没有设置还原点也没有搞砸):

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\jar_auto_file]
@=""
"EditFlags"=hex:00,00,00,00

[HKEY_CLASSES_ROOT\jar_auto_file\shell]

[HKEY_CLASSES_ROOT\jar_auto_file\shell\open]

[HKEY_CLASSES_ROOT\jar_auto_file\shell\open\command]
@="\"C:\\Program Files\\Java\\jdk1.7.0_60\\bin\\javaw.exe\" -jar \"%1\" %*"

这假设.jar文件的jar_auto_file值为(Default)。如果不是,请执行以下操作:
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\.jar]
@="jar_auto_file"

p.s. 我在注册表中发现的一个问题是,jarfile 与 Netbeans、Chrome 和 java.exe 以及 Applications\java.exe 相关联。我删除了整个节点(在导出它后,只是为了如果它是必要的可以放回去;但实际上不是)。现在我的注册表中没有 jarfile,所有 .jar 文件都像以前一样执行。

这表现为在“控制面板”中显示与 .jar 文件关联的多个文件类型。您需要这个:

enter image description here

如果“推荐程序”中显示了多个项目,请搜索注册表以查找 jarfile 并(首先导出,然后)删除该节点:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.jar


1
这对我在Windows 10上有效,据我所知,每个基于GUI的干预都已完全删除。我将以上答案复制/粘贴到.reg文件中,将路径更改为EXE(我的是不同版本,而且是JRE而不是JDK),它立即解决了问题。我希望我能给予多个赞。 - Christopher Schultz

2

前提条件:确保已安装JRE(包含在JDK中)。

解决方案

  1. 打开regedit并导航到 Computer\HKEY_CLASSES_ROOT\jar_auto_file\shell\open\command

  2. 将“-jar”添加到值数据中。例如,从 "C:\Program Files\Java\jdk-15.0.1\bin\java.exe" "%1" 更改为 "C:\Program Files\Java\jdk-15.0.1\bin\java.exe" "-jar" "%1"

  3. 完成

如果问题仍然存在,请确保在项目属性中配置了正确的主类。


0

我在处理.jar文件时遇到了同样的问题,尝试了所有方法后才意识到我安装了多个版本的Java。删除不必要的版本解决了我的问题。可能是因为.jar文件在不同版本的JRE之间混淆了。


0

只是想提供我的意见,我曾经遇到过这个问题,可能是清单中的某些内容导致的。我通过以不同的方式生成可执行的JAR文件来解决这个问题:

之前的开发人员是从Eclipse中生成可运行的JAR文件(右键单击项目 -> 导出... -> 可运行的JAR文件),对于每个人都可以正常工作。然后我来了,通过在pom.xml中配置Maven插件("assembly")来生成可运行的JAR文件,因此经典的Maven构建将生成可运行的JAR文件。

这对我来说很好用(从cmd和双击都可以),但对最终用户来说却不行(他们仍然可以从cmd运行该工具,但无法通过双击JAR文件运行它)。

我从Eclipse中生成了可运行的JAR文件,现在每个人都很高兴。不确定为什么由Maven生成的JAR文件不能通过双击运行,但既然完成了工作,我就懒得再去深入调查了。希望这个半成品的建议能帮助到某些人。


-5

只是为了让路过的任何人都清楚地知道问题的答案,我在这里放置我的解决方案(由于8小时规则,我之前无法这样做):

好吧,在查看和重新查看我的代码后,我发现问题出在一些涉及检测64位系统的胡言乱语上,它加载了错误的dll。为什么它可以通过命令行工作而不能通过双击启动我不知道,也可能永远不会知道,但现在通过双击可以工作了,所以我很高兴。对于造成的麻烦,我很抱歉。


7
我想我可能有同样的问题,但目前还不清楚如何解决这个 BS 的问题。 - Thorn
“BS'ery”对于如何实际解决这个问题没有任何帮助。 - Justin Wiseman
4
你提到你发现了问题,但没有具体描述这个问题的细节,也没有描述你为纠正问题所做的事情。 - purgatory101
你应该更详细地描述你的问题和解决方案,这样其他遇到类似问题的人可以从你的经验中受益。Eric在他的回答中发布了一个好的解决方案。 - Jason C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接