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.
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.
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.
There are several reasons why the environment variable CLASSPATH is (and should be) ignored:
- 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.
- 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.
- 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).
- Java EE app servers all ignore global CLASSPATH. They don't count on it.
- Java IDEs all have their own conventions for setting a project CLASSPATH. Learn them.
- 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.
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 ...
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.