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.

houghofferness.blogspot.com

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

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel