Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4356783
Votes 0
Synopsis Running java.exe with "-jar" ignores the classpath
Category java:runtime
Reported Against 1.3 , 1.4.2
Release Fixed
State 11-Closed, Will Not Fix, request for enhancement
Priority: 5-Very Low
Related Bugs 4459663 , 5087182
Submit Date 26-JUL-2000
Description




java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)java

When using the "Main-Class" feature of a jar's manifest file and the "-jar"
option to java.exe, the classpath environment variable seems to be ignored. I
have created a testcase:

Other.java:
-------------------------------------------------
    public class Other { }
-------------------------------------------------

Main.java:
-------------------------------------------------
    public class Main
    {
        public static void main (String [] args)
        {
            Other other = new Other();
        }
    }
------------------------------------

manifest:
------------------------------------
    Manifest-Version: 1.0
    Main-Class: Main
-------------------------------------

Instructions for setting up the test:
1. Create the files "Other.java", "Main.java", and "manifest" with the contents
listed above.
2. javac Main.java
3. javac Other.java
4. jar -cf other.jar Other.class
5. jar -cfm main.jar manifest Main.class

Now, execute this sequence of commands:

    SET CLASSPATH=other.jar
    java -jar main.jar
    
    SET CLASSPATH=other.java;main.java
    java Main

    java -cp other.jar;main.jar Main

In the first execution, there is an exception:

    Exception in thread "main" java.lang.NoClassDefFoundError: Other

even though class Other is in the classpath. The other two commands run
correctly (no exceptions, no output, as expected). It seems that the "-jar"
option is causing java.exe to ignore the classpath, which is incorrect: the
classpath should be used like it is in the last two example executions.

It is possible to use the "Class-Path" header field name in the manifest to
work around this issue. This is inappropriate for many applications for because
the "Class-Path" header field requires the JAR creator to know the location of
the classes it depends on. The application should not have to know the location
of the file.

I noticed this bug when using JAXP. Since I wanted to be able to switch parser
implementations at runtime (one of the goals of JAXP), I did not know the
locations of the SAX classes: they could be in "parsers.jar" or "xerces.jar"
or "xml4j.jar", for example. Because of this I could not put the "Class-Path"
header in my JAR file to reference any one of these. I can send a more
elaborate testcase that uses JAXP to demonstrate this problem if needed.
(Review ID: 107498) 
======================================================================
Work Around




Use the "Class-Path" header in the manifest.
======================================================================
Evaluation
  xxxxx@xxxxx   2001-05-14
This is the intended behavior.  As documented in the SDK docs (regarding
the -jar option of the java command):

http://java.sun.com/j2se/1.3/docs/tooldocs/win32/java.html

"When you use this option, the JAR file is the source of all user
 classes, and other user class path settings are ignored."

An alternative approach is for the application to choose its
parser at runtime and explicitly load it with a new URLClassLoader.


  xxxxx@xxxxx   2001-06-06
Additional comments with respect to JDC ...

This feature request (not bug) could be implemented fairly trivially,
but would create backward compatibility issues.  In particular, users
who were (perhaps unknowingly) depending on their classpath NOT
interfering, could see new failures.  This is adequate reason to reject
the change request.

In general, it is quite appropriate for the application to be insolated
from the vagaries of the user environment.  Since the CLASSPATH variable
is set by the user, and not by the application writer, it is desirable
that it have no effect on the application.

In the example from the original bug report, the submitter wanted to use
the classpath to provide a user selectable software component (XML
parser) for the application.  While this may have been a convenient
hack, this is certainly not a mechanism to be used by product quality
software.  This application could certainly have been coded to use
another argument or property or GUI to choose a parser, and load it with
a new classloader.

Another user also indicates a problem with Java Web Start, but does not
give any details.  I don't understand why the classpath is required in
addition to the jar file.

Another user has another variation which is similar to javac (in that it
processes java souce code), which does use the CLASSPATH (in the absense
of other options).  In this case, using the CLASSPATH variable saves
some typing, but introduces ambiguity.  The classpath used to run the
application is not (should not) be the classpath used to process the
input application.  We shouldn't be encouraging this kind of amibiguity.
Comments
  
  Include a link with my name & email   

Submitted On 04-AUG-2000
JMS
I have the same problem, also while programming with saxp
and parser.
Here, java -jar MyApp ignores the Class-Path: in the
manifest.
(JRE 1.2.2)


Submitted On 04-AUG-2000
JMS
Sorry...I was wrong. It works...


Submitted On 23-AUG-2000
briansmith
Note that JMS's problem was the opposite of the reported 
problem and that this bug _is_ valid.


Submitted On 22-SEP-2000
briansmith
The current behaviour is correct with respect to the 
current documentation. I believe that the fourth rule below 
is too restrictive, especially in the case where both "-
jar" and "-cp" are provided on the command line. I think 
that, at the very least, if an explicity classpath is 
provided on the command line along with '-jar' then that 
classpath should be searched after searching for classes 
inside that jar file.

Also, regarding JAXP: The JAXP documentation should 
explicitly mention that the JAXP implementation needs to be 
in the extensions directory (jre/lib/ext) in order for 
programs run with "-jar jarfile.jar" to find it. This is 
especially important with the JRE feature that lets users 
run JAR files by double-clicking. 

This is from the "How Classes are Found" document 
(http://java.sun.com/j2se/1.3/docs/tooldocs/findingclasses.h
tml):

The java launcher puts the user class path string in the 
java.class.path system property. The possible sources of 
this value are:

[.. info about ".", "CLASSPATH", and "-cp" snipped ...]

* The JAR archive specified by the -jar option, which 
overrides all other values. If this option is used, all 
user classes come from the specified archive. 


Submitted On 22-SEP-2000
briansmith
"rule 4" in my previous comment refers to the text "* The 
JAR archive..."


Submitted On 27-FEB-2001
briansmith
AFAICT, This will not be be changed in JDK 1.3.1 (now in 
beta) and we would likely have to wait for JDK 1.4 or later 
to have this changed. Just so my previous comments are 
clear, the current implementation is working as documented 
and designed, but I think the design is flawed. A Jar file 
should be able to its exact classpath but there should at 
least be an option to use the CLASSPATH environment 
variable when using the '-jar' parameter. And, when the 
interpreter is run with "-jar XXX -cp YYY;ZZZ" then it is 
only sensible to to use a combination of the jar file's 
Class-Path header and the classpath specified with the "-
cp" parameter. This would also a person to write a command 
line like "java -jar XXX -cp %CLASSPATH%" to explicitly 
indicate that they want the CLASSPATH variable to be 
included in the final classpath. I believe the wording in 
the "How Classes are Found" document should be replaced 
with the following wording, and this new design should be 
implemented as described in the new wording.

The user class path is specified as a string, with a colon 
(:) separating the class path entries on Solaris, and a 
semi-colon (;) separating entries on Win32 systems. The 
java launcher puts the user class path string in the 
java.class.path system property. The possible sources of 
this value are: 

* The default value, ".", meaning that user class files are 
all class files in the current directory (or under it, if 
in a package). 

* The value of the CLASSPATH environment variable, which 
overrides the default value. 

* The value of the -cp or -classpath command line option, 
which overrides both the default value and the CLASSPATH 
value. 

* The JAR archive specified by the -jar option, which 
overrides the default value and the CLASSPATH value.
The classpath will consist of the archive specified in the -
jar option, followed by the value of the archive's 
manifests's Class-Path entries if any, followed by the 
value specified in the -cp or -classpath options, if any. 
Note that if you want to use the -jar option and use the 
CLASSPATH value at the same time, you can use a command of 
the form "java -jar XXX.jar -cp %CLASSPATH%" on Windows or 
its Solaris equivelent.


Submitted On 19-APR-2001
wamoz
I'd also like to point out that this
Usage: java [-options] class [args...]
           (to execute a class)
   or  java -jar [-options] jarfile [args...]
           (to execute a jar file)

where options include:
    -cp -classpath <directories and zip/jar files separated 
by ;>
                  set search path for application classes 
and resources
    -D<name>=<value>
                  set a system property
    -verbose[:class|gc|jni]
                  enable verbose output
    -version      print product version and exit
    -showversion  print product version and continue
    -? -help      print this help message
    -X            print help on non-standard options

Specifically states that [-options] can be used, and goes 
on to define [-options] as including -cp which DIRECTLY 
implies that the classpath will be honoured.


Submitted On 19-APR-2001
wamoz
The development team's interpretation of the spec is 
absurd. "Overrides" does not mean "ignores", it 
means "takes precedence over". So the jar file indicated by 
the -jar switch should behave as though it were the first 
element in the classpath.

My interpretation of the spec also happens to neatly 
describe a simple workaround for this singular piece of 
stupidity;

java -cp thejar.jar;%classpath% packagename.mainclassname

I'm sorry I can't be more polite, but I've lost two days to 
this problem. This sort of crap I expect from Microsoft, 
not Sun.


Submitted On 03-MAY-2001
raller
The use of Java Web Start makes the problem even worse, as 
the workarround mentioned by Wamoz cannot be used. It must 
be possible eighter to transfer the current classpath to 
the JAR file, or to give an absolute (not just relative) 
path in the manifest file.


Submitted On 06-MAY-2001
briansmith
> java -cp thejar.jar;%classpath% packagename.mainclassname

This doesn't work if you are trying to run a JARred 
application by double-clicking on the JAR file.


Submitted On 21-MAY-2001
toddwebb
PLEASE!! You MUST include the classpath in 
the "java.class.path" system property!  It is just asinine 
to drop the classpath when calling an executable jar file!

I also don't think its enough to just include it if the -
cp/-classpath option is specified.  The entire classpath 
should still be available in the "java.class.path" property 
with the JAR file pre-pended to that path.  Especially 
considering the -cp option is incompatible with paths that 
contain spaces.  And please don't tell me to use 
the "Progra~1" to replace "Program Files" in the 
Windows2000 classpath- Many developers work on multi-user 
machines where they are NOT administrators and can not make 
changes to the system classpath.  It is asking alot to have 
each person create yet another script just to correct all 
the paths in the classpath- and if you are using jini, 
JDBC, and 3rd party code somewhere under "Program Files", 
this list can be sizeable. 


I have an application that parses Java source files and 
expands wildcard imports (import java.awt.*) into 
individual class imports.  This works excellent & allows 
you to do wildcard imports to quickly write a class, then 
expand the imports later to conform to your project coding 
standards.  Everyone else on my project wanted to use it, 
so I jarred up the various classes to produce a slick, 
portable, executable jar file.  All the user would have to 
do is drop it in the root directory and call:
ImportExpander.jar MySource.java

Great! Except it was completely broken!!  This app 
ABSOLUTELY needs to search the entire class path to find 
all referenced classes!  This, of course, was dropped and 
only ImportExpander.jar was returned for 
the "java.class.path" property.  Now that System.getenv() 
is no longer supported, there is NO OTHER WAY TO GET THE 
CLASSPATH FROM JAVA!  This short-sighted decision makes 
many applications unworkable from a JAR.  This is one of 
those instances where you sit as a developer scratching 
your head in extreme frustration thinking "here is yet 
another thing I CAN NOT do from Java". . .  why am I using 
Java again?  Maybe I should check out C-sharp!

The workaround, to tell the users of my JAR to use:
java -cp ImportExpander.jar;%CLASSPATH% 
com.mega.util.SourceImportExpander MySource.java
is unacceptable.  So is putting that command in a script or 
a .bat file.  Besides the fact that is would still break 
most of the time for the reason listed above, either way 
defeats the main purpose of using the JAR file in the first 
place- simplicity.


Submitted On 22-MAY-2001
briansmith
This will now be in the Top 25 RFE list so it will be 
getting a lot of exposure in the short term; I expect this 
will be fixed by JDK 1.5


Submitted On 23-MAY-2001
briansmith
Okay, so they closed it when it got to the Top 25. That was 
nice.


Submitted On 24-MAY-2001
jeffy124
check out bug #4459663, it better illustrates the problem.  
I wrote that report a few weeks ago before I discovered this
one.

I think perhaps the statement "When you use this option, the
JAR file is the source of all user classes, and other user 
class path settings are ignored." entered by the evaluator
of this report needs to be revised before this bug can be 
worked on.


Submitted On 29-MAY-2001
raller
Someone ought to open a new error report, reporting an 
error in the specification. It is clearly a problem for all 
trying to use JAR files - especially with webstart


Submitted On 18-DEC-2001
dalton5
I pass my application to Java Web Start, in my jar i have 
some dtd, since I pass to Java web start this code doesn't 
work any more, now always return null:
static public InputStream getInputStream(String 
pathFileName )throws MalformedURLException{
    URL [] tabUrl = new URL[]{
      new URL("file://"+pathFileName)
      };
    URLClassLoader ucl = new   URLClassLoader(tabUrl);
    URL url = ucl.getResource(pathFileName);
    return ucl.getResourceAsStream(pathFileName);
  }
If someone had a workaround... thanks


Submitted On 18-DEC-2001
dalton5
I pass my application to Java Web Start, in my jar i have 
some dtd, since I pass to Java web start this code doesn't 
work any more, now always return null:
static public InputStream getInputStream(String 
pathFileName )throws MalformedURLException{
    URL [] tabUrl = new URL[]{
      new URL("file://"+pathFileName)
      };
    URLClassLoader ucl = new   URLClassLoader(tabUrl);
    URL url = ucl.getResource(pathFileName);
    return ucl.getResourceAsStream(pathFileName);
  }

I work with this code to get my resources:
/**
  *To get a InputStream from a file wich can be in a jar or 
a simple directoryn work also if the jar is NOT
  *in the classpath, this is for that than the method is 
not static.
  * ex If your search this file com/nortel/test/Myfile.txt 
it's can be in a simple directory or in a jar
  * (in classpath or not because of java web start wich 
lost classpath)
  * @param String pathFileName path to file ex= 
com/nortel/test/Myfile.txt 
  * @return InputStream for com/nortel/test/Myfile.txt or 
null if the specified file is not found.
  */
    private InputStream _getInputStream(String 
pathFileName) throws java.io.IOException{
    InputStream is = null ;
    try
    {
         String s = this.getClass().getResource
(fileName).getPath() ;
         System.out.println(s);
        //if file is found in a jar or zip file
        //we load it from jar file
        //we search in first in zip file because of the 
deployement
        //==================================================
======== 
        //is in a jar solution...
        //=======================  
        //if file is in jar it's like:
        //<Pr>:<---------System path------------------->!<--
-----relatif path------------------------->
        //file:/C:/Java Web 
Start/<....>RMFileAndJar.jar!/com/nortel/oam/gui/resources/d
td/classdef.dtd
        if(s!=null && s.indexOf(':')+1>0 &&  s.indexOf('!')
>0){
         s = s.substring(s.indexOf(':')+1, s.indexOf('!')) ;
         JarFile jarfile = new JarFile(s) ;
         ZipEntry zipEntry = jarfile.getEntry
(pathFileName) ;
         is = jarfile.getInputStream(zipEntry);
         }
         else{//we try to load it from "classpath" or jar 
in classpath
             URL [] tabUrl = new URL[]{
              new URL("file://"+pathFileName)
              };
             URLClassLoader ucl = new   URLClassLoader
(tabUrl);
             URL url = ucl.getResource(pathFileName);
             is =  ucl.getResourceAsStream(pathFileName);
         }
    }catch(IOException e){
      //nothing to do, we return null
   }
   return  is;
  }//end private InputStream 


Submitted On 17-JAN-2002
SJS
> This feature request (not bug) could be 
> implemented fairly trivially, but would 
> create backward compatibility issues.  
> In particular, users who were (perhaps 
> unknowingly) depending on their classpath 
> NOT interfering, could see new failures.  
> This is adequate reason to reject the change request.

Doesn't that depend on *how* it is implemented? If it
were implemented with a -X option, then there would not
be any backwards compatibility issue.

Note that the even with the current behavior for

java -jar jarfile.jar

the *expected* (and reasonable) behavior of 

java -cp $CLASSPATH -jar jarfile.jar

is that the classpath specified on the command line 
would NOT be ignored. It's disturbing to have command-line
options silently ignored, much less to have them behave in
such an arbitrary manner.

As the evaluation says: "We shouldn't be encouraging
this kind of amibiguity".


Submitted On 01-MAR-2002
Joele
We have the same problem reading & writing a .conf file 
from a .jar executable file. The .conf file is not visible 
from the .jar although we set the .conf in thhe ClassPath.
How to resolve this problem?
Mariella Pupo


Submitted On 15-MAR-2002
sgsst
I'd suggest adding a new directive to the Manifest file. 
Something like: Class-Path: %CLASSPATH%; it would eliminate 
the backward compatibility issue because the executable jar 
creator would have to explicitly say, in the manifest, to 
include the external Classpath.  That way, old executable 
jars wouldn't have the new directive in them and would work 
as before.


Submitted On 29-MAR-2002
anodynos
I was also terribly frustrated to see this terrible BUG 
(its not a feature, its a bug in the specs) 
a) the executable JARS cant use anything else other that 
what is inlcuded in the jar it self - eg. a jdbc DBAdmin 
application can't use any JDBC driver in the classpath (the 
deployer has to include every possible JDBC driver in the 
executable jar!)
b) the -cp myclasspaths option is SILENTLY ignored - this 
is unacceptable! (and also the envirionment variable)

So, another proof java on the desktop was born dead (!), 
something we already knew.... Imagine M$ Windows 
applications couldn't use DLL's and OCX's already on the 
system! What a monolithic behaviour! So much for Java byte 
code that runs everywhere - I think it crashes everywhere. 
Its getting too late for a resurection now - drop Webstart 
& and the hype. Java is only good for J2EE, for how long 
now with .NET breathing on it neck ?


Submitted On 19-FEB-2003
jdcalan
To those working on the JVM, I would advise you to look 
again at this.

I don't know any applications that run off a single JAR.

This would be a great feature if it were more flexible - there 
have been many good suggestions to solve this easily without 
compatibility or ambiguity.

With this feature, configuration of a system with startup files 
would be child's play as all main classes could be specified in 
the Manifests.

This is also an issue when considering obfuscation of bytecode

thanks


Submitted On 19-MAY-2003
alwilkin
Will this be fixed in JVM 1.5?



PLEASE NOTE: JDK6 is formerly known as Project Mustang