views:

122

answers:

6
  • In this post, I was told that -jar ignores all the -cp and $CLASSPATH. Why is this? Is there any reason for this?
  • I was also told -cp option also ignores the $CLASSPATH. Why is this? Is there any good reason for this?
+4  A: 

It's to avoid clashes in the classpath whenever you distribute your application to run on different environments. In most of the cases you'd like your application to be independent from the platform specific configuration. If the $CLASSPATH contains references to classes with (either unawarely or awarely) the same package and classname, it would get precedence in classloading before the classes which you included in your application's classpath. This may lead to unexpected application behaviour or potential security holes.

BalusC
+3  A: 

jar is supposed to be a standalone program with self-contained libraries. If you want to include other classpaths, you may need to do something like

java -cp jar1:jar2:$CLASSPATH some.class.with.main

BalusC answered the other question.

William
A: 

There is no sane enough reason to explain this apparent "absurdity", in my words. From one of the bugs in the Sun bug database, one can only infer that a developer did not account for the fact that the classpath could be specified via the CLASSPATH environment variable, or via the -cp option. By the time the issue was found, the release was more or less public, with the effect that the fix would cause backward compatibility issues.

Vineet Reynolds
@Vineet - you are attempting to rewrite history. A more balanced reading of that bug report is 1) it was a deliberate design decision with a good justification, and 2) in retrospect the justification remains valid. The fact that changing the semantics of `-jar` would break lots of things is just another reason not to change ... not the primary reason. The primary reason is that Sun/Oracle think that the current behaviour is correct. (FWIW, I agree)
Stephen C
Well, I'm not. The spec was incomplete, as it never addressed the user classpath being inherited via the environment, so it was never deliberately good. In retrospect, it might sound good, but as one of the comments from the analysis itself states, the fix was trivial.
Vineet Reynolds
@Vineet - I don't know *where* you got that from. The spec clearly stated/states that $CLASSPATH is ignored when "-jar" is used. The bug report even quotes from the online documentation to make this clear.
Stephen C
@Stephen, point taken. I must rephrase my earlier statement as "The author of the specification did not believe that it would be necessary to inherit the user classpath from the environment". Evidently, this is not serious enough of a problem given that there are workarounds available.
Vineet Reynolds
+1  A: 

There are several reasons why the environment variable CLASSPATH is (and should be) ignored:

  1. A global CLASSPATH for all projects makes no sense at all. It can't be the same for all projects, and you don't want one massive one that's reapplied to all projects.
  2. You can't count on it being set, so depending on it is a bad idea. Code that works on one machine suddenly doesn't work when it's moved. How do you communicate the necessary environment settings? Better not to use them.
  3. Java EE app servers all have their own conventions (e.g., all JARs in WEB-INF/lib and all .class files in WEB-INF/classes are automatically in the CLASSPATH for a web app).
  4. Java EE app servers all ignore global CLASSPATH. They don't count on it.
  5. Java IDEs all have their own conventions for setting a project CLASSPATH. Learn them.
  6. All Java IDEs ignore global CLASSPATH. They don't count on it.

I don't have a global CLASSPATH on any machine that I use. It's not necessary. I'd recommend learning how CLASSPATH works and stop relying on environment variables.

duffymo
A: 

If you really want an application to be launchable using "-jar" and to also pick up classes via the user's $CLASSPATH environment variable, you should be able to do this by having the application create its own classloader. (You could even make your application look for a "-cp" argument after the "-jar" argument.)

However, I think it would be bad idea to do that. The main point of executable JAR files is to isolate the application from the vagaries of the environment in which the user happens to launch the application.

If you want to do hacky things with your application classpath, a simpler approach is to create a wrapper script that assembles the effective classpath however you want to, then launches the application with a "-cp" option. You could even pull the "Class-path" out of various JAR files' manifests and incorporate that ...

Stephen C
+1  A: 

Correct or not, I long for a -jar-cp flag. That would be obvious and direct enough to not be a security risk or break current behavior.

With APIs like java.util.ServiceLoader, it is entirely reasonable to wish to add/remove services from the classpath. You shouldn't have to loose that functionality because you used Main-Class in your manifest.

David Blevins