最近,我阅读了很多有关Java类加载过程的信息。我经常碰到一些文字,这些文字声称在运行时无法将类添加到类路径并在没有类加载器黑客(URLClassLoaders等)的情况下加载它们
据我所知,类是动态加载的。这意味着仅在需要时才将其字节码表示形式加载并转换为java.lang.Class对象。
因此,如果尚未启动JVM,是否应该在JVM启动后将JAR或 .class文件添加到类路径并加载这些类?(要清楚:在这种情况下,类路径只是文件系统上的文件夹。“添加JAR或 .class文件”只是意味着将它们放在此文件夹中。)
如果不是,这是否意味着在JVM启动时搜索类路径,并且所找到类的所有全限定名称都缓存在内部“列表”中?
如果您能在回答中为我提供一些参考资料,对您会很好。最好是正式的SUN文档:Sun JVM Spec。我已经阅读了规范,但是找不到关于类路径的任何信息,并且如果它在JVM启动时完成了确定。
聚苯乙烯
这是一个理论问题。我只想知道是否有可能。我没有想要实现的实用方法。我只是渴求知识:)
由于没有人可以给我一个明确的答案,也没有人提供与文档相应部分的链接,因此我自己提供一个答案。不过,我要感谢所有试图回答这个问题的人。
简短答案:
在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文件夹。您显然必须根据放置课程的位置对此进行更改。
所以这是我执行的步骤:
补充笔记:
当我将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)