Failed to Read Class-path Attribute From Manifest of Jar
Back to the basics of Java — Role 2: The JAR
In the first role I introduced a simple example explaining how to utilize the classpath correctly. I volition use this example for this part every bit well, and so if you did not create that even so you can copy it from the first part before proceeding if you desire to follow along.
JAR
A jar file is only a blazon of archive used to packet java class files and associated resources for distribution. If nosotros remember from the last article, our file construction was like this.
ClasspathProject/
|
---> src/java/myprogram/
|
---> Chief.java
|
---> utils/
|
---> Util.java
|
---> bin/myprogram/
|
---> Main.grade
|
---> utils/
|
---> Util.form
Permit's create an executable jar containing the class files. Showtime nosotros navigate to the root directory.
Outset endeavor — the messy way
So nosotros run this command [1].
> jar --create --file project.jar bin/myprogram/Main.class bin/myprogram/utils/Util.class
- --create (or -c) : create a new archive
- --file (or -f) : filename of the archive
- file(southward) : the files to include in the annal
Allow's run it.
> java -jar projection.jar
no main manifest attribute, in project.jar
It seems like information technology cannot observe a manifest. Then let's inspect what the contents are. Hither are 3 commands that give you the exact same output then I will show all of them but will from now on use the last ane.
> jar --list --file project.jar (alternative 1)
> jar -t -f projection.jar (culling 2)
> jar -tf project.jar (culling 3)
META-INF/
META-INF/MANIFEST.MF
bin/myprogram/Principal.class
bin/myprogram/utils/Util.grade
- --list (or -t) : list the contents of a jar
- --file (or -f) : the jar file
Information technology doesn't look very expert. Let's find out what the manifest contains.
> jar --excerpt --file project.jar (alternative 1)
> jar -xf project.jar (alternative 2)
- --extract (or -x) : extract the content from a jar
So print the manifest.
> cat META-INF/MANIFEST.MF
Manifest-Version: ane.0
Created-By: xiii.0.ii (Oracle Corporation)
Is this fixable? Certain, I'll quickly bear witness the fix. The minimum fix is to update the manifest with a classpath.
> echo "Course-Path: bin/" > manifest.txt
> jar --update --file project.jar --manifest manifest.txt
- --update (or -u) : update a jar file
- --manifest (or -m) : manifest file to include data from
Let's run it again.
> coffee -jar project.jar
no main manifest attribute, in project.jar
Okey same trouble because information technology is not an executable jar, there is no main form in the jar manifest. Withal, we can run it past specifying the jar in the classpath.
> java -cp project.jar myprogram.Main
Here is 1337
Let's update our manifest file past adding a principal class aspect and update the jar.
> echo "Main-Class: myprogram.Main" >> manifest.txt
> jar -u -f project.jar -m manifest.txt
Aug xxx, 2021 eleven:52:26 AM java.util.jar.Attributes read
WARNING: Duplicate proper noun in Manifest: Class-Path.
Ensure that the manifest does not take duplicate entries, and that bare lines separate individual sections in both your manifest and in the META-INF/MANIFEST.MF entry in the jar file.
You can ignore this warning because if we inspect the MANIFEST.MF file as shown above y'all will come across that it looks good.
> jar -xf project.jar
> cat META-INF/MANIFEST.MF
Manifest-Version: 1.0
Created-Past: 13.0.2 (Oracle Corporation)
Class-Path: bin/
Main-Class: myprogram.Main
But if you lot wanted, you could accept overridden the manifest.txt file with just one new line containing the main-form attribute and information technology would be changed in the MANIFEST.MF file in the jar.
Alternatively, you lot can actually specify the main-class aspect on the command line to update the jar, which is a quick way of irresolute the aspect.
> jar -u -f project.jar --chief-class myprogram.Main
> java -jar projection.jar
Here is 1337
- --main-class (or -eastward) : changes the Main-Class aspect in the manifest
Now we can run it like unremarkably.
> java -jar project.jar
Hither is 1337
Okey, so this was messy. Let's try and simplify things. Commencement, let's clear the directory of the files to start over.
> rm -rf META-INF/ manifest.txt project.jar
2d attempt —the simpler way
Now I'll try to make this a bit more succinct.
> jar -c -e myprogram.Main -f project.jar -C bin/ myprogram/Main.grade -C bin/ myprogram/utils/Util.class
- -C: changes directory and includes the provided file (2 argument flag, note the space)
Permit'due south audit the content.
> jar -tf project.jar
META-INF/
META-INF/MANIFEST.MF
myprogram/Main.class
myprogram/utils/Util.grade
Already here you tin can see that it looks a lot better, no bin directory anywhere. We should be able to run this directly.
> java -jar project.jar
Hither is 1337
Alright, great. However, nosotros can actually simplify the command a little fleck.
> jar -cfe project.jar myprogram.Main -C bin/ .
> java -jar projection.jar
Here is 1337
Here I specified the directory and a wildcard using the dot (.) which takes everything inside the bin directory.
Side notation
The ordering of the arguments here is of import. If you for instance did this instead:
> jar -cfe myprogram.Primary project.jar -C bin/ .
The command would succeed, merely you would end up with a file called myprogram.Main with a primary class attribute of projection.jar.
> ls
bin lib myprogram.Chief src > coffee -jar myprogram.Primary
Mistake: Could non observe or load main class project.jar
Caused past: coffee.lang.ClassNotFoundException: projection.jar
Library jar
For this part, I'g going to motion out Util.class into its own jar file similarly to what I did in the first office of this series when explaining the classpath.
Then the new file structure will look like this.
ClasspathProject/
|
---> src/coffee/myprogram/
|
---> Main.java
|
---> utils/
|
---> Util.coffee
|
---> bin/myprogram/
|
---> Master.grade
|
---> lib/myprogram/
|
---> utils/
|
---> Util.class
And we will run the following commands to generate our jar files.
> jar -cfe project.jar myprogram.Master -C bin/ .
> jar -cf projectutils.jar -C lib/ .
Now if we effort and run the project.jar we will plainly become an error because it cannot detect the Util class.
> java -jar project.jar
Exception in thread "principal" java.lang.NoClassDefFoundError: myprogram/utils/Util
at myprogram.Primary.chief(Master.java:eight)
Acquired by: java.lang.ClassNotFoundException: myprogram.utils.Util
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base of operations/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.coffee:521)
... ane more
And so how practice nosotros run this? If we remember from the classpath commodity we can specify the jars on the classpath like this.
> java -cp projection.jar:projectutils.jar myprogram.Primary
Here is 1337
Just what if nosotros want to make project.jar an executable jar file so that the command that failed in a higher place works? Well, then we need to use the manifest similar so.
> echo "Master-Class: myprogram.Main" > manifest.txt
> echo "Class-Path: projectutils.jar" >> manifest.txt
> jar -cfm projection.jar manifest.txt -C bin/ .
> java -jar projection.jar
Here is 1337
Annotation that the Course-Path attribute is a relative path to the created jar file.
Source: https://medium.com/javarevisited/back-to-the-basics-of-java-part-2-the-jar-6e923685d571
0 Response to "Failed to Read Class-path Attribute From Manifest of Jar"
Post a Comment