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.
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.
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.
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.
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.
发布评论
评论(6)
这是为了避免每当您分发应用程序以在不同环境中运行时类路径中发生冲突。在大多数情况下,您希望应用程序独立于特定于平台的配置。如果
$CLASSPATH
包含对具有(无意或有意)相同包和类名的类的引用,则在类加载中,它将优先于您包含在应用程序类路径中的类。这可能会导致意外的应用程序行为或潜在的安全漏洞。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 应该是一个具有独立库的独立程序。如果您想包含其他类路径,您可能需要执行类似
BalusC 回答其他问题的操作。
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
BalusC answered the other question.
在这两种情况下,限制的原因是为了避免1意外或肆意/考虑不周地覆盖有效类路径。
如果您确实希望应用程序可以使用“-jar”启动,并通过用户的 $CLASSPATH 环境变量获取类,那么您应该能够通过让应用程序创建自己的类加载器或使用自定义启动器来实现此目的。 (您甚至可以让您的应用程序在“-jar”参数之后查找“-cp”参数。)
同样,您可以修改第一种情况下的行为。
然而,我认为这样做是个坏主意。可执行 JAR 文件的要点是将应用程序与用户启动应用程序的环境的变化隔离开来。
如果您想对应用程序类路径做些奇怪的事情,一种更简单的方法是创建一个包装器脚本,以您想要的方式组装有效的类路径,然后使用“-cp”选项启动应用程序。您甚至可以从各种 JAR 文件的清单中提取“类路径”并将其合并...
1 - 显然,它并不能阻止某人完全更改类路径。但停止这种行为将是一个坏主意,如果我们假设用户可以获得本地管理员权限等,那么技术上可能是不可能的。
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.
环境变量 CLASSPATH 被(并且应该)被忽略有几个原因:
我使用的任何机器上都没有全局 CLASSPATH。没必要。我建议学习 CLASSPATH 的工作原理并停止依赖环境变量。
There are several reasons why the environment variable CLASSPATH is (and should be) ignored:
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.
无论正确与否,我都渴望一个
-jar-cp
标志。这将是显而易见和直接的,不会构成安全风险或破坏当前的行为。使用 java.util.ServiceLoader 等 API ,希望从类路径中添加/删除服务是完全合理的。您不必因为在清单中使用了
Main-Class
而放弃该功能。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.用我的话来说,没有足够理智的理由来解释这种明显的“荒谬”。从Sun bug数据库中的一个bug,人们只能推断出开发人员没有考虑到类路径可以通过 CLASSPATH 环境变量或通过 -cp 选项指定。当问题被发现时,该版本或多或少是公开的,其结果是修复会导致向后兼容性问题。
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.