5

I have searched the internet and I have searched stackoverflow and found many many posts asking this question, yet there isn't ever a concrete answer.


The short version is: I have a jar file which references other jar files in the manifest. I then run the jar file with java -jar test.jar, but it doesn't add the jar dependencies to the classpath.


Long version: I made a little experiment in order to confirm that it wasn't something special about my project. I created a simple Java Project in eclipse, with only 1 class. All this class does is write the classpath to std-out:

package test;

import java.net.URL;
import java.net.URLClassLoader;

public class Test {
  public static void main(String[] args){
    ClassLoader cl = ClassLoader.getSystemClassLoader();
    URL[] urls = ((URLClassLoader)cl).getURLs();
    for(URL url: urls){
      System.out.println("CP: "+url.getFile());
    }
  }
}

Then I created a "lib" folder and put a random jar file inside and added it to the classpath. The folder structure now looks like this:

Test
|- src/test/Test.java
|- lib/mysql-connector-java-3.1.14-bin.jar

Now when I run it from Eclipse I get the following output:

CP: /home/username/workspace/Test/bin/
CP: /home/username/workspace/Test/lib/mysql-connector-java-3.1.14-bin.jar

Ok, now I use Eclipse to export the project to a runnable jar. I choose the option "Copy required libraries into sub-folder next to the generated jar".

This creates the following structure:

/tmp/Test
|- test.jar
|- test_lib/mysql-connector-java-3.1.14-bin.jar

If I look into the Test.jar that was created by Eclipse, it looks like this:

test.jar
|- test/Test.class
|- META-INF/MANIFEST.MF

The contents of the MANIFEST.MF are:

Manifest-Version: 1.0
Class-Path: . test_lib/mysql-connector-java-3.1.14-bin.jar
Main-Class: test.Test

And yes, there is an empty line after the Main-Class attribute (I mention this because some people posted online that the cause could be a missing newline at the end).

So, everything looks fine. I run it with java -jar test.jar and get the following output:

CP: /tmp/Test/test.jar

So the classpath contains only the jar file that I want to run. The Class-Path: attribute in the MANIFEST is completely ignored. The same thing happens if I run it with java -cp test.jar test.Test

How does one use the Class-Path attribute in the MANIFEST.MF properly? I can't figure it out for the life of me. Especially since -cp and -jar are not compatible, I don't know how I could specify the classpath while also using the -jar argument.

Thanks a lot in advance.


A few more things I can answer in advance:

  • "Is there a line break after the last line?" - Yes
  • "Could it be eclipse malforms the MANIFEST.MF?" - Could be, but I have the same problem when I make the jar with ant. So if both eclipse and ant malform the manifest, I don't know how I should format it.
  • "What platforms, Java versions have you tried?" - I tried Java8 on Windows 10, as well as Java6, Java7 and Java8 on Fedora Linux.
4
  • And what happens if, instead displaying the classpath, you simply try to load a class that is in the jar 'like, for example, Class.forName("com.mysql.jdbc.Driver")?
    – JB Nizet
    Commented Aug 26, 2015 at 12:16
  • Damn... that works. This means my problem with my other project is elsewhere, because there I'm getting ClassNotFoundExceptions
    – RHS
    Commented Aug 26, 2015 at 12:19
  • I don't understand the purpose of the period on the Class-Path line. Also, try simply putting the two jars together in the same directory, and making the Class Path line like this: Class-Path: mysql-connector-java-3.1.14-bin.jar. You shouldn't have to re-export the project as long as you have an archiving application to be able to edit the manifest. Commented Aug 26, 2015 at 12:25
  • Yeah, I wondered about the period as well. That's how eclipse generated it. I can change the manifest using file-roller. But through the help of JB Nizet I realized my experiment is set up wrong. If I try to instanciate anything from the jar file it actually works. so everything is working as it should. Now I only have to figure out why it doesn't work in my other project...
    – RHS
    Commented Aug 26, 2015 at 12:31

1 Answer 1

1

Ok, thanks to JB Nizet's comment I figured out that everything is working fine. It doesn't print out the classpath but I can access the classes from the library. So my experiment was set up wrong. This is bad news for me, as my other project still doesn't work, and it is too complex to post here.

2
  • I would just make sure you have the jar referenced properly by comparing it to the test, or even by putting the test class in your other project's jar and running it, just to make sure. Then experiment with different ways of referencing the classes from the external jar. I haven't seen your code, but if I had to guess, that's where the problem is. Commented Aug 26, 2015 at 12:36
  • 1
    Thanks for the comment. I found the culprit now. In my other project (where the jar was created with ant) it was the existence of an "INDEX.LIST" file in the jar file. I read about this before, but since I (mistakenly) thought my test project also doesn't work and it didn't have an index file, I didn't investigate this further.
    – RHS
    Commented Aug 26, 2015 at 13:06

Not the answer you're looking for? Browse other questions tagged or ask your own question.