Jar file failing to execute with NullPointerException when it runs fine unpacked - java

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 "main" 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(...).

Related

Error: Could not find or load main class when trying to run jar file

I'm trying to create a JAR file of my Java code. There are four classes - A.java, B.java, C.java, and D.java. A.java has the main method. These are in a folder called src, and my manifest file is outside of src, and all of my .class files are in bin which is inside src. I created a MANIFEST.MF with the following contents:
Manifest-Version: 1.0
Main-Class: src/A
I then use the command jar cmf MANIFEST.MF A.jar src/bin/*.class src/GraphFile.txt src/ProblemA.txt src/ProblemB.txt (there are a few text files I need to include as well in my JAR file). Then, when I run java -jar A.jar ProblemA.txt GraphFile.txt (note that ProblemA.txt and GraphFile.txt are input files that my program accepts and uses), I get the following error:
Error: Could not find or load main class src.A
Caused by: java.lang.ClassNotFoundException: src.A
Can anyone explain what I am doing wrong or any steps I am missing? Unfortunately, I cannot post the actual code because this is for a class project, but I just need to get it compiled into a JAR file for submission! Thanks for any help.

Assigning a version to a jar file

Simple issue: I'd like to assign a new version\build number every time I issue a new jar file to my customers.
I understood that a manufest file is involved but I fail to get the version whatever I have tried so far.
My jar project has two packages under a common "com" package: "main" and "loginRequest".
My main class ("Main") is under the "main" package.
My manifest file is :
Manifest-Version: 1.0
Main-Class: main.Main
Specification-Version: 1.1
I tried to build the jar using eclipse (excluding the src files), including the manifest.
I also tried the following:
jar -cvfm v11_4_WebExClientEE.jar ..\..\v11_4_WebExClientEE.mf main\Main.class
which retruned me
"added manifest
adding: main/Main.class(in = 1206) (out= 677)(deflated 43%)"
and then:
java -jar v11_4_WebExClientEE.jar
which returned me
Exception in thread "main" java.lang.NoClassDefFoundError: main/Main (wrong name: com/main/Main)
etc.
In my main class ctor I added:
Package p = this.getClass().getPackage();
System.out.println("v11_4_WebExClientEE spec Version : " + p.getSpecificationVersion());
Can you please advise?
Thanks!
The clue to what you did wrong is in the exception message:
... NoClassDefFoundError: main/Main (wrong name: com/main/Main)
The JVM has found the entry for your entry point class (according to your "Main-Class" attribute) but the classloader has thrown an exception that the JAR entry pathname doesn't match the full package name for your class. (The classloader was expecting "main/Main" but the actual package name was "/com/main/Main" ... according to the class file contents.)
Following the details I gave, should it be com/main/*.class ?
Yes. That is what you should put on the jar command line to add the classes with the correct JAR paths. (Or at least something like that. The key thing is that the argument(s) should correspond to the full entry path that you require for the JAR file; i.e. the fully qualified classname(s).)
and what should I put instead of java/util/ and java.util ?
The Name attribute probably should not be there at all. A "Name" attribute introduces a manifest section for an entry in the JAR file.
The "Implementation-Title" attribute is purely descriptive. You can put whatever you want there.
Before you go any further, I strongly recommend that you read the JAR file specification carefully. Pay attention to what the spec says about the manifest syntax, and what the manifest attributes mean.
We first create a text file named Manifest.txt with the following contents:
Name: com/main/
Specification-Title: Main Common Class
Specification-Version: 1.2
Specification-Vendor: Example Tech, Inc.
Implementation-Title: com.main
Implementation-Version: build57
Implementation-Vendor: Example Tech, Inc.
We then create a JAR file named MyJar_1.2.jar by entering the following command:
jar cfm MyJar_1.2.jar Manifest.txt MyPackage/*.class

NoClassDefFoundError when attempting to run from command line

Apologies in advance - I know there are many, many, many very similar questions but I wanted to ask something specific to my situation.
I have a bunch of java and jar files in the same directory. I am able to compile fine and thus end up with a number of class files in the same dir. But when I go to execute the program it gives a NoClassDefFoundError saying it can't find the specified class:
C:\Users\DB\Desktop\nextreports-integration-demo\src\ro\nextreports\integration>
java -cp ".;*.jar" SimpleDemo
Exception in thread "main" java.lang.NoClassDefFoundError: SimpleDemo (wrong nam
e: ro/nextreports/integration/SimpleDemo)
I tried the same thing from a higher-level dir but it made no difference:
C:\Users\DB\Desktop\nextreports-integration-demo\src>java -cp ".\ro\nextreports\
integration\*.jar;.\ro\nextreports\integration" SimpleDemo
Exception in thread "main" java.lang.NoClassDefFoundError: SimpleDemo (wrong nam
e: ro/nextreports/integration/SimpleDemo)
The package statement in the source file is:
package ro.nextreports.integration;
I have a feeling I'm overlooking something very elementary. Thanks in advance.
Edit: Thanks very much. It works with the following:
java -cp ".\ro\nextreports\integration\nextreports-engine-6.3.jar;.\ro\nextreports\integration\commons-jexl-2.1.1.jar;.\ro\nextreports\integration\commons-logging-1.1.1.jar;.\ro\nextreports\integration\derby-10.10.1.1.jar;.\ro\nextreports\integration\itext-2.1.7.jar;.\ro\nextreports\integration\itext-rtf-2.1.7.jar;.\ro\nextreports\integration\itextpdf-5.0.6.jar;.\ro\nextreports\integration\jcalendar-1.3.2.jar;.\ro\nextreports\integration\jcommon-1.0.15.jar;.\ro\nextreports\integration\jfreechart-1.0.12.jar;.\ro\nextreports\integration\jofc2-1.0.1.jar;.\ro\nextreports\integration\mysql-connector-java-5.1.23-bin.jar;.\ro\nextreports\integration\mysql-connector-java-5.1.23-bin.jar;.\ro\nextreports\integration\poi-3.7.jar;.\ro\nextreports\integration\winstone-lite-0.9.10.jar;.\ro\nextreports\integration\xstream-1.3.1.jar;" ro.nextreports.integration.SimpleDemo
But why can I not use wildcards for the *.jar files? For instance, the following leads to a NoClassDefFoundError for a class in any jar file I don't make explicit:
java -cp ".;.\ro\nextreports\integration\*.jar" ro.nextreports.integration.
SimpleDemo
Suppose this is your directory tree:
src/
ro/
nextreports/
integration/
SimpleDemo.class
From your package declaration, your compiled class should be in the integration subdiretory. Check that there really is a SimpleDemo.class in that directory. If that is correct, its classpath includes the contents of the src directory.
That means that, if you didn't have any JAR dependencies, you could run your application from the src directory like this:
java -cp . ro.nextreports.integration.SimpleDemo
You need to use the fully qualified class name.
Since you do have jars, you have to include them in the classpath as well. Suppose you have one JAR in the directory above src, and another in the current directory, you could use:
java -cp ../one.jar;another.jar;. ro.nextreports.integration.SimpleDemo
If you run it from another directory, it will still work if you review the classpath's relative directories or use absolute directories to describe your classpath. I am not sure but usually the current directory is always included in the classpath by the java executable.

Hadoop: strange ClassNotFoundException

I am getting a classnotfound exception. The class which is claimed to be not found does not exist, but the class name is set as the path to the list of input files for my map reduce jobs.
INFO server Running: /usr/lib/hadoop/bin/hadoop --config /var/run/cloudera-scm-agent/process/155-hue/JOBSUBD/hadoop-conf jar tmp.jar /user/hduser/datasets/ /user/hduser/tmp/job_20/ mongodb://slave15/db_8.job_20
Exception in thread "main" java.lang.ClassNotFoundException: /user/hduser/datasets/
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at org.apache.hadoop.util.RunJar.main(Runjar.java:190)
As we can see, the /user/hduser/datasets/ is the path to the input files. Why am I getting this error as ClassNotFoundException? Why does it see it as a class?
I found my own error. I have a package structure. I need to specify my package information
/usr/lib/hadoop/bin/hadoop
--config /var/run/cloudera-scm-agent/process/155-hue/JOBSUBD/hadoop-conf
jar tmp.jar org.myorg.tmp /user/hduser/datasets/
/user/hduser/tmp/job_20/ mongodb://slave15/db_8.job_20
In my tool, there is no option for giving the package as argument to Java. So I need to have no packaging. But then I am having the following error since the argument before this input file path is missing.
My classes are directly in the tmp.jar in its root. I mean no org.myorg etc...
SOLUTION:
jar cmf [manifest_file] [jar_name.jar] -C [folder_of_classes] [path_for_jar_file]
it will merge the content of the manifest_file with the generated manifest file in the jar archive. Include the following line in the manifest_file
Main-Class: [Name_Of_Class]
Whether or not there's a package hierarchy (and if there isn't, you've done Something Wrong) you still need to give it the name of the class containing main.
For example, the docs have an example where the main class is org.myorg.WordCount. Even if WordCount was in the default package, it should be specified if the jar file doesn't include a main class in the manifest:
bin/hadoop jar /usr/joe/wordcount.jar WordCount /usr/joe/wordcount/input /usr/joe/wordcount/output
I'd assume you could also specify the main class in the manifest as with any jar; the class argument is shown as optional in those same docs.

How to create executable .jar file with netbeans

I'd like to make "double-click" cli application but still don't get how.
I know I should propably somehow edit manifest but that is all. I googled ofc. but no success.
Thanks for any tips.
Here is the output from build, run, and manifest:
compile:
Created dir: /home/nick/NetBeansProjects/SemestralWork/dist
Building jar: /home/nick/NetBeansProjects/SemestralWork/dist/SemestralWork.jar
Not copying the libraries.
To run this application from the command line without Ant, try:
java -jar "/home/nick/NetBeansProjects/SemestralWork/dist/SemestralWork.jar"
jar:
BUILD SUCCESSFUL (total time: 1 second)
java -jar /home/nick/NetBeansProjects/SemestralWork/dist/SemestralWork.jar
Exception in thread "main" java.lang.NoClassDefFoundError: semestralwork/Main
Caused by: java.lang.ClassNotFoundException: semestralwork.Main
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:319)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
at java.lang.ClassLoader.loadClass(ClassLoader.java:264)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:332)
Could not find the main class: semestralwork.Main. Program will exit.
MY MANIFEST created with build:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.1
Created-By: 14.0-b08 (Sun Microsystems Inc.)
Main-Class: semestralwork.Main
Class-Path:
X-COMMENT: Main-Class will be added automatically by build
These two lines tell you all you need to know:
Exception in thread "main" java.lang.NoClassDefFoundError: semestralwork/Main
Caused by: java.lang.ClassNotFoundException: semestralwork.Main
And a further clue is dropped by the manifest output:
Main-Class: semestralwork.Main
This means that the JAR file is looking for a package named semestralwork and a class named Main inside it. It fails at this point because it cannot find either the semestralwork package or the Main class.
As you pointed out in your question, the problem is indeed in the manifest file. You can edit this directly in your JAR file if you like, but a better idea would be to do this from Netbeans:
Click on `File --> Project Properties (semestralwork)'
In the dialog that opens, on the tree on the left select Run
Then, on the right, under the field labeled Main class:, enter the fully qualified class name of the class that you want executed when run from the command line.
In your case, as I see from your comment on #Aaron's answer, if your main class is in a file called encryption.java, and it is in the default package (no package), just enter encryption.
Once this is done, do a clean and build, then try running it from the command line again.
HTH
Since I encountered the same problem, I can clarify the solution a little bit.
You must create main Java class outside your method (for example-default_package folder), and then invoke your method(folder), e.g import your_folder.connected_class; in that main class.
Hopefully I could help someone with the same problem.
It's easier to make a .exe from a .jar without netbeans.
Here are my suggestions:
1. Use a special application for this(ex: JSmooth, JEXECreator etc)
2. Make a C++ program that starts a JVM (see this tutorial)
The default class search path may be the issue. You should try changing directory to the location the jar is and launching with java -jar Semestral.jar. Also you may have misnamed the main class. Please also include your package structure.
Open the JAR file with a ZIP tool (or try less ... if you're on Linux or jar tvf ...). Make sure there is a directory semestralwork in there which contains a file Main.class.
It's Easy. Download a copy of netbeans. Make a new project in netbeans. Goto your main class in the Projects Explorer. This should be folder "YourProject" As the class YOURPROJECT.JAVA . It is this yourproject.java file that you want to start with. Just write your code into the public static void main area. You can run the program with the green play button in the top toolbar.

Categories

Resources