$CLASSPATH和-cp在Java中的作用是什么?

4
  • 在这篇文章中,使用-jar选项会忽略所有的-cp和$CLASSPATH。
  • 在这篇文章中,使用-cp选项同样会忽略$CLASSPATH。

它们存在的好理由是什么呢?

6个回答

9

这是为了避免在将应用程序分发到不同环境中运行时出现类路径冲突。在大多数情况下,您希望应用程序独立于特定平台的配置。如果$CLASSPATH包含对具有相同包和类名的类的引用(无论是无意识还是有意识的),它将在类加载之前优先于您在应用程序类路径中包含的类。这可能导致意外的应用程序行为或潜在的安全漏洞。


5

jar应该是一个独立的程序,具有自包含的库。如果您想包含其他类路径,您可能需要执行以下操作:

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

BalusC回答了另一个问题。


3
在这两种情况下,限制的原因是为了避免意外或者莽撞/不考虑后果地覆盖有效的类路径。
如果你真的希望一个应用程序能够使用“-jar”启动,并且还可以通过用户的$CLASSPATH环境变量来获取类,那么你可以让应用程序创建自己的类加载器,或者使用自定义启动器。(你甚至可以让你的应用程序在“-jar”参数后寻找“-cp”参数。)
同样地,在第一种情况下,您也可以修改行为。
然而,我认为这样做是一个坏主意。可执行JAR文件的主要目的是将应用程序与用户启动应用程序的环境的不确定性隔离开来。
如果你想对你的应用程序类路径进行hacky操作,一个更简单的方法是创建一个包装脚本,按照你想要的方式组装有效的类路径,然后使用“-cp”选项启动应用程序。你甚至可以从各种JAR文件的清单中提取“Class-path”,并加入其中...
注释1:显然,这并不能阻止某些人完全改变类路径。但是,阻止这种行为是一个坏主意,而且可能在技术上是不可能的,如果我们假设用户可以获得本地管理员权限等。

1

有几个原因说明为什么环境变量CLASSPATH被(并且应该被)忽略:

  1. 全局的CLASSPATH对于所有项目来说都没有意义。它不能对所有项目都是相同的,你也不想要一个庞大的CLASSPATH被应用到所有项目中。
  2. 你不能指望它被设置,所以依赖它是一个坏主意。在一台机器上工作的代码突然在移动时就无法工作了。如何传达必要的环境设置?最好不要使用它们。
  3. Java EE应用服务器都有自己的约定(例如,WEB-INF/lib中的所有JAR文件和WEB-INF/classes中的所有.class文件都自动成为Web应用程序的CLASSPATH)。
  4. Java EE应用服务器都忽略全局CLASSPATH。他们不依赖它。
  5. Java IDE都有自己的约定来设置项目的CLASSPATH。学习它们。
  6. 所有Java IDE都忽略全局CLASSPATH。他们不依赖它。

我在任何我使用的机器上都没有全局CLASSPATH。这是不必要的。我建议学习CLASSPATH的工作原理,停止依赖环境变量。


我运行一个有自己类路径的应用程序,它在jar中硬编码。它调用我的另一个jython应用程序。我想为jython提供额外的类。为什么让主Java应用程序选择我的jython类的位置是不好的呢?其次,我不明白证明CLASSPATH是完全无意义的如何能解释当未使用“-cp”选项时是可以的。 - Val

1

无论对错,我都渴望一个-jar-cp标志。这将足够明显和直接,不会成为安全风险或破坏当前行为。

有了像java.util.ServiceLoader这样的API,希望从类路径中添加/删除服务是完全合理的。您不应该因为在清单中使用了Main-Class而失去该功能。


为了让其他可能被这个问题困扰的读者明白,我需要强调一下,你失去了该功能是因为你使用了Main-Class属性(通过使用“-jar”选项),而不是因为JAR文件中存在Main-Class属性。 - Stephen C

0

没有足够合理的理由来解释这个明显的“荒谬”,用我的话来说。从Sun bug数据库中的一个漏洞中,我们只能推断出开发人员没有考虑到类路径可以通过CLASSPATH环境变量或-cp选项指定。当问题被发现时,发布已经是公开的了,修复将会导致向后兼容性问题。


1
你正在试图重写历史。对那个错误报告的更加平衡的阅读是:1)这是一个有充分理由的故意设计决策,2)回顾起来,这个理由仍然有效。改变“-jar”的语义将会破坏很多东西,这只是不改变的另一个原因,而不是主要原因。主要原因是Sun/Oracle认为当前的行为是正确的。(顺便说一下,我同意) - Stephen C
我并不是这样认为。规范不完整,因为它从未涉及用户类路径通过环境继承的问题,所以它从未被刻意地优化过。回想起来,这听起来可能很好,但正如分析本身的评论之一所述,修复是微不足道的。 - Vineet Reynolds
我不知道你从哪里得到的信息。规范明确说明当使用“-jar”时,$CLASSPATH将被忽略。缺陷报告甚至引用在线文档以明确这一点。 - Stephen C
@Stephen,收到。我必须重新表述我之前的陈述:“规范的作者认为从环境继承用户类路径是不必要的”。显然,这不是一个严重的问题,因为有可用的解决方法。 - Vineet Reynolds

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接