4

I want to reference a jar file in fixed location for use by multiple executable jars rather than include that jar in each of the executables. I have the following setup which works fine

commons-math3-3.6.1.jar exists in directory testgradle. TestGradle.jar contains the main method and exists in directory testgradle/build/libs

from testgradle/build/libs I run:

java -jar TestGradle.jar

And things work fine. The manifest in TestGradle.jar contains:

Manifest-Version: 1.0
Class-Path: ../../commons-math3-3.6.1.jar
Main-Class: com.spgxyz.test.testg

But I want to address commons-math3-3.6.1.jar with an absolute path so that executable jars such as TestGradle.jar can use it from whichever directory they reside in. However, if I change TestGradle.jar manifest to include the full path:

Manifest-Version: 1.0
Class-Path: C:\Users\Admin\workspace\TestGradle\commons-math3-3.6.1.ja
 r
Main-Class: com.spgxyz.test.testg

Then the command:

java -jar TestGradle.jar

run from testgradle/build/libs produces:

Error: Could not find or load main class com.spgxyz.test.testg
Caused by: java.lang.ClassNotFoundException: com.spgxyz.test.testg

I tried various edits to the manifest to try to cure this such as:

Manifest-Version: 1.0
Class-Path: . C:\Users\Admin\workspace\TestGradle\commons-math3-3.6.1.
 jar
Main-Class: com.spgxyz.test.testg

Manifest-Version: 1.0
Class-Path: TestGradle.jar C:\Users\Admin\workspace\TestGradle\commons
 -math3-3.6.1.jar
Main-Class: com.spgxyz.test.testg

These both produce the same error. If someone could shed some light on what's going on here I'd be very grateful. Running on windows.

stegzzz
  • 407
  • 4
  • 9

1 Answers1

4

Class-Path attribute is interpreted as a list of URLs, so, to use an absolute path (represented with a URL here), it should start with schema and use forward slashes.

Try the following:

Class-Path: file:///C:/Users/Admin/workspace/TestGradle/commons-math3-3.6.1.jar
Roman Puchkovskiy
  • 11,415
  • 5
  • 36
  • 72
  • 1
    The solution posted by Roman Puchkovskiy works but I'm wondering why, after reading quite a few articles, I didn't find anything that would have led me to that solution. For example in the Oracle [documentation](https://docs.oracle.com/javase/8/docs/technotes/tools/windows/classpath.html) there are several places where an absolute path e.g. c:\java\... appears to be used. – stegzzz Dec 24 '17 at 16:22
  • 1
    In the document to which you posted a link here, they talk about **file paths** (which you feed to `-cp` command line parameter), and file paths can contain backslashes. But as it can be seen here https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#classpath , `Class-Path` element of a manifest contains **URLs**. URLs have their own rules, and backslashes are not good there. Also, `C:` in the very beginning may be interpreted as URL protocol, so we have to use `file:///` explicitly. – Roman Puchkovskiy Dec 24 '17 at 16:32
  • 2
    Note that that link clearly and repeatedly states that the URLs must be relative URLs. An absolute URL like this one may happen to work, but is not officially supported. The better solution is to copy commons-math3-3.6.1.jar to the directory containing each .jar which wishes to use it, and put `Class-Path: commons-math3-3.6.1.jar` in the manifest. – VGR Dec 25 '17 at 03:02
  • But the [link](https://docs.oracle.com/javase/8/docs/technotes/tools/windows/classpath.html) I referred to clearly and repeatedly used absolute paths in the classpath and it is easy to see how this could result in confusion. For example [here](https://docs.oracle.com/javase/8/docs/technotes/tools/windows/findingclasses.html#BABBFCIJ) it states 'The manifest can define a JAR class path, which further extends the class path...' which does not immediately suggest that there is a different set of rules for class path defined in manifest. – stegzzz Dec 25 '17 at 09:07
  • The text at https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#classpath says "The manifest for an application can specify one or more relative URLs referring to the JAR files and directories for other libraries that it requires. These relative URLs are treated relative to the code base from which the containing application was loaded." If you're a Java dev, you know that URL means you can use file:/// . Another implication: an entry like lib/foo.jar is relative to the original jar, not relative to the working directory of the java executable. – Cheeso Feb 14 '19 at 22:38
  • If you have many jar file do you do we add file:/// in front of all the jar files? – MR AND Jul 16 '19 at 10:14
  • 1
    It says towards the bottom of this link: https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#classpath "Currently, the URLs must be relative to the code base of the JAR file for security reasons. " I suspect if you are getting absolute paths to work, it shouldn't be assumed it will continue to work or would work on all platforms. – Dave L. Jan 20 '20 at 22:19
  • @VGR When I put just the name of the JDBC driver into the manifest class-path (`postgresql.jar`) and the class loader is not able to find the operating system jar located in `/usr/share/java`. When I put the absolute path into the manifest the class loader finds the jar. How should the class loader know the path to the jar, if just the relative path is in the manifest? – ceving Aug 21 '20 at 07:12
  • @ceving It looks at the classpath of the Java runtime. For each entry in the classpath, Java will look for postgresql.jar relative to that entry. If your manifest has `Class-Path: postgresql.jar`, Java will expect postgresql.jar to be in the same directory as one of the jars already in the Java program’s classpath. – VGR Aug 21 '20 at 11:49