一尘不染

Java类路径在JVM启动之后是最终的吗?

java

最近,我阅读了很多有关Java类加载过程的信息。我经常碰到一些文字,这些文字声称在运行时无法将类添加到类路径并在没有类加载器黑客(URLClassLoaders等)的情况下加载它们

据我所知,类是动态加载的。这意味着仅在需要时才将其字节码表示形式加载并转换为java.lang.Class对象。

因此,如果尚未启动JVM,是否应该在JVM启动后将JAR或
.class文件添加到类路径并加载这些类?(要清楚:在这种情况下,类路径只是文件系统上的文件夹。“添加JAR或

.class文件”只是意味着将它们放在此文件夹中。)

如果不是,这是否意味着在JVM启动时搜索类路径,并且所找到类的所有全限定名称都缓存在内部“列表”中?

如果您能在回答中为我提供一些参考资料,对您会很好。最好是正式的SUN文档:Sun JVM
Spec
。我已经阅读了规范,但是找不到关于类路径的任何信息,并且如果它在JVM启动时完成了确定。

聚苯乙烯

这是一个理论问题。我只想知道是否有可能。我没有想要实现的实用方法。我只是渴求知识:)


阅读 177

收藏
2020-12-03

共1个答案

一尘不染

由于没有人可以给我一个明确的答案,也没有人提供与文档相应部分的链接,因此我自己提供一个答案。不过,我要感谢所有试图回答这个问题的人。

简短答案:

在JVM启动时,类路径不是最终的。

实际上,您可以在JVM启动后将类放在类路径中,然后将它们装入。


长答案:

为了回答这个问题,我遵循了用户未知的建议,并编写了一些测试程序。

基本思想是有两个类。第一类是实例化第二类的主要类。启动时,第二个类不在类路径中。cli程序启动后,将提示您按Enter。在按Enter之前,您将第二个类复制到类路径上。按Enter后,将实例化第二个类。如果类路径在JVM启动时是最终的,则将引发Exception。但事实并非如此。因此,我认为classpath在JVM启动时不是最终的。

以下是源代码:

JVMTest.java

package jvmtest;

import java.io.Console;
import jvmtest.MyClass;

public class JVMTest {
  public static void main(String[] args) {
    System.out.println("JVMTest started ...");

    Console c = System.console();
    String enter = c.readLine("Press Enter to proceed");
    MyClass myClass = new MyClass();
    System.out.println("Bye Bye");
  }
}

MyClass.java

package jvmtest;

public class MyClass {
  public MyClass() {
    System.out.println("MyClass v2");
  }
}

文件夹结构如下所示:

jvmtest/
  JVMTest.class
  MyClass.class

我使用以下命令启动了cli程序:

> java -cp /tmp/ jvmtest.JVMTest

如您所见,我在/ tmp / jvmtest中有我的jvmtest文件夹。您显然必须根据放置课程的位置对此进行更改。

所以这是我执行的步骤:

  1. 确保jvmtest中只有JVMTest.class。
  2. 从上方使用命令启动程序。
  3. 只是要确保按回车键。您应该看到一个异常,告诉您找不到任何类。
  4. 现在再次启动程序。
  5. 程序启动后,提示您按Enter,将MyClass文件复制到jvmtest文件夹中。
  6. 按回车。您应该看到“ MyClass v1”。

补充笔记:

当我将MyClass类包装在罐子中并运行上面的测试时,这也起作用。

我在运行Mac OS X 10.6.3的Macbook Pro上运行了此程序

> Java -version

结果是:

java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02-279-10M3065)
Java HotSpot(TM) 64-Bit Server VM (build 16.3-b01-279, mixed mode)
2020-12-03