4
  • In this post, using -jar option ignores all the -cp and $CLASSPATH.
  • In this post, using -cp option also ignores the $CLASSPATH.

Is there any good reason for them?

Community
  • 1
  • 1
prosseek
  • 182,215
  • 215
  • 566
  • 871

6 Answers6

9

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
  • 1,082,665
  • 372
  • 3,610
  • 3,555
5

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 Niu
  • 15,798
  • 7
  • 53
  • 93
3

In both cases, the reason for the restrictions it to avoid1 accidental or wanton / ill-considered overriding of the effective classpath.

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, or using a custom launcher. (You could even make your application look for a "-cp" argument after the "-jar" argument.)

Likewise, you could modify the behavior in the first case.

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 ...


1 - Clearly, it doesn't stop someone changing the classpath entirely. But stopping that would be a bad idea, and probably isn't technically possible if we assume that the user can get local admin privilege, etcetera.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
1

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
  • 305,152
  • 44
  • 369
  • 561
  • I run one app that has its own classpath, hardcoded in jar. It calls my another jython app. I wanted to supply the extra classes for jython. Why it is bad the main java app to pick the locations of my jython classes? Secondly, I do not understand how proving that CLASSPATH is total nonsense can explain that it is ok when `-cp` option is not used. – Val Oct 12 '13 at 16:36
1

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
  • 19,178
  • 3
  • 53
  • 68
  • Just to be clear (for the benefit of other readers who might be confused by this), you are losing the capability because you >>used<< the Main-Class attribute (by using the `-jar` option), not because the Main-Class attribute is present in the JAR file. – Stephen C Dec 27 '20 at 03:57
0

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
  • 76,006
  • 17
  • 150
  • 174
  • 1
    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 Aug 03 '10 at 23:19
  • 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 Aug 03 '10 at 23:23
  • 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 Aug 04 '10 at 00:00
  • @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 Aug 04 '10 at 01:02