Jar file failing to execute with NullPointerException when it runs fine unpacked
I'm attempting to restructure a legacy application and reduce the steps needed to deploy. To do this, I'm packaging all the class files, and Resources into a jar file.
I'm using this command to jar everything:
jar -cfm ../Deploy/JEmu.jar Manifest.txt *.class Resources/
My manifest file looks like this:
Manifest-Version: 1.0
Created-By: 1.2.2 (Sun Microsystems Inc.)
Main-Class: JEmu
Name: JEmu.class
The class that is the entry point is JEmu.class, which is packaged in the jar, but when I run the jar I get this error:
java -jar JEmu.jar
Exception in thread "ma开发者_如何转开发in" java.lang.ExceptionInInitializerError
Caused by: java.lang.NullPointerException
at javax.swing.ImageIcon.<init>(Unknown Source)
at ControlBar.<init>(ControlBar.java:88)
at JEmu.<clinit>(JEmu.java:85)
Could not find the main class: JEmu. Program will exit.
I'm not exactly sure what is causing that.
Line 88 of ControlBar is:
stopButton = new JButton( new ImageIcon( classLoader.getResource("Resources/stop.gif")));
What am I doing wrong, it all works when it's not packaged into a jar?
classLoader.getResource("Resources/stop.gif")
probably cannot find the specified resource. When this happens, it returns null
, hence the NullPointerException
.
The problem is that the VM is not able to find the resource named "Resources/stop.gif"
. The reason for this is that the stop.gif file is located in the package "Resources"
as it is in the base of the JAR file. By default, the getResource method will start with the package of the class from which the classloader was retrieved. In the case of your code it would be the package in which the Thread class is located. The end result would be that the VM looks for the image in the location "/java/lang/Resources/stop.gif"
, which is not where your image is located.
If you are looking for a fixed location, i.e., Resource directory located in base of JAR, then make sure to prefix your URL string with '/' as in:
classLoader.getResource("/Resources/stop.gif");
Another thing to think about is whether you need to use the ClassLoader from the current Thread. Typically the ClassLoader used by your application class would be more appropriate. You can retrieve that by executing something similar to this.getClass().getResource(...)
.
精彩评论