【问题标题】:Does jvm load all the classes mentioned by the classpath?jvm 会加载类路径中提到的所有类吗?
【发布时间】:2017-05-25 17:21:03
【问题描述】:

当我们使用 -cp 命令调用 java 命令时,我们会提供一些目录和 jar 文件。 jvm 是否会加载类路径中提到的所有类,或者它只是 jvm 在需要时将查找加载的所有类的超集?

【问题讨论】:

  • 标题中包含ClassLoader这个词,但是你的问题没有提到。您是否忘记提出部分问题?
  • @immibis jvm 是否加载类路径中提到的所有类
  • 感谢 Chetan,编辑了问题。

标签: java classloader


【解决方案1】:

jvm 是否加载类路径中提到的所有类或者它只是 jvm 将查找加载的所有类的超集 需要吗?

JVM 根据需要从类路径中加载类,即当找到该类的引用时,它会被加载。 JVM中还有一个类加载器的层次结构,由父类加载器加载的类被较低的类加载器使用。

【讨论】:

  • 我编写了一个简单的 HelloWorld 类,它不导入或使用任何其他 3rd 方 jar。当我使用“java -verbose:class HelloWorld”运行它时,我看到 JVM 加载了来自 rt.jar 的这么多类。仍然对 Bootstrap 加载器加载的核心 java 类感到困惑。所有的类都是从 rt.jar 加载的吗?
  • @hsingh JVM 需要 rt.jar 中存在的类来设置 java 运行时环境。我不确定是否所有的类,但肯定有一些是从 rt.jar 加载的
【解决方案2】:

涉及两个概念

  • 加载中
  • 初始化

初始化一个类将初始化字段并执行静态块。发生这种情况的确切时刻对应用程序语义很重要,因此它是precisely defined

初始化需要先加载;但是加载更多的是JVM的内部概念。即使不需要,JVM 也可以并且被允许积极地预加载类。此过程不会影响应用程序语义,并且对应用程序是不可见的。

就应用程序而言,如果我们得到一个类的Classobject,则必须已经加载了一个类,例如来自 Foo.classClass.forName 或其他反射 API。我们可以检查Class 的属性,而不必触发初始化。

一个重要的约束——我们必须为相同的类名(并且来自相同的类加载器)获取相同的Class 对象。 Class 对象是已加载类的 表示。

【讨论】:

  • 关于您的最后一点,我认为Class 对象需要 相同。我认为这只是实现的一个好习惯。需要在 JLS 中找到。
  • @SotiriosDelimanolis - 一个不好的类加载器甚至可能返回一个错误的 Class 对象!我认为这句话的意思是“合法”的类加载器应该那样做。在 JLS 和 javadocs 中有很多提到“ 类对象”,例如static synchronized 对“类对象”进行操作;如果一个类可以有 2 个 Class 对象,那将没有多大意义。此外,Class 不会覆盖equals,并且有大量代码直接使用== 来检查类相等性,即使在JLS 中的示例中也是如此。
【解决方案3】:
  1. JVM 仅加载引用的类,而不是类路径中 jar 中存在的每个类
  2. 类的加载是通过分层方式进行的
  3. 类路径中的 jar 过多只会占用更多磁盘空间
  4. JVM 仅使用物理内存 (RAM) 中的内存。

【讨论】:

    【解决方案4】:

    类的加载按顺序进行并按位置查找。 -cp 属于下面列出的第三类。大多数应用程序类应通过 -cp 提供,否则它将查找环境变量 CLASSPATH。

    扩展框架利用类加载委托机制。当运行时环境需要为应用程序加载新类时,它会按顺序在以下位置查找该类:

    1)Bootstrap 类: rt.jar 中的运行时类、i18n.jar 中的国际化类等。

    2)已安装的扩展: JRE 的 lib/ext 目录中的 JAR 文件中的类,以及系统范围的特定于平台的扩展目录(例如 /usr/jdk/packages /lib/ext 在 Solaris™ 操作系统上,但请注意,此目录的使用仅适用于 Java™ 6 及更高版本。

    3) 类路径: 类,包括 JAR 文件中的类,位于系统属性 java.class.path 指定的路径上。如果类路径上的 JAR 文件具有带有 Class-Path 属性的清单,则还将搜索由 Class-Path 属性指定的 JAR 文件。默认情况下,java.class.path 属性的值为 .,即当前目录。您可以通过使用 -classpath 或 -cp 命令行选项或设置 CLASSPATH 环境变量来更改该值。命令行选项会覆盖 CLASSPATH 环境变量的设置。

    https://docs.oracle.com/javase/tutorial/ext/basics/load.html

    【讨论】:

    • 那么-cp 会导致类自动加载?
    • -cp 是我们向运行时环境显示的类路径,它可以在其中找到不在前两个位置(rt.jar 和扩展名)的所需类。如果在三个位置中的任何一个都找不到所需的类,则最终会出现 classnotfound 异常
    • 问题不在于-cp 是如何工作的,也不在于如何查找类。问题是使用-cp 列出的类/jar 是否会自动加载。您的回答解释了搜索类的顺序。那不是OP所要求的。您关于加载的答案的唯一部分是按顺序加载类,这没有回答问题。
    • 它按顺序在提到的位置查找类文件。这并不意味着它会加载所有类。它会在提到的位置查找类文件。您的类路径可以包含 n 个类,但将加载所需的类。希望这清楚。
    • 没错。我的意思是您的回答需要明确提及在引用时将加载所需的类
    【解决方案5】:

    它不会加载所有类,但它知道在需要时到哪里查找它们。

    它们将在第一次需要时加载。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-11
      • 1970-01-01
      • 1970-01-01
      • 2016-12-06
      • 1970-01-01
      • 2015-03-15
      • 2015-01-07
      • 1970-01-01
      相关资源
      最近更新 更多