我正在编写一个简单的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文件。为什么它可以通过命令行工作而不能通过双击运行,我不知道,也可能永远不会知道,但是现在通过双击可以运行了,所以我很高兴。抱歉给您带来麻烦。