rt.jar 如何加载到 jvm - hotspot 中?

How rt.jar loaded in jvm - hotspot?

我正在学习 jvm 的工作原理。现在我试图弄清楚 运行 rt.the jar 在什么时候被加载到 VM 中。我可以在代码的哪个位置看到它?

这取决于您所说的 'rt.jar is loaded into the VM' 的实际含义。 HotSpot 不会加载 内存中的整个rt.jar。相反,每当 bootstrap class 加载程序尝试加载 class 时,它就会懒惰地查找相应的 JAR 条目。有时 JVM 甚至不需要访问 jar 来加载系统 class,例如当改用 CDS archive. Also note, there is no longer rt.jar since JDK 9 - there are modular images 时。

找到when/where JVM 首先打开rt.jar 的一个简单方法是在调试器下运行 Java 并在ZIP_Open 处设置断点.

Breakpoint 1, 0x00007ffff5632880 in ZIP_Open () from /usr/java/jdk8u275/jre/lib/amd64/libzip.so
(gdb) bt
#0  0x00007ffff5632880 in ZIP_Open () from /usr/java/jdk8u275/jre/lib/amd64/libzip.so
#1  0x00007ffff67d65cb in ClassLoader::create_class_path_entry(char const*, stat const*, bool, bool, Thread*) () from /usr/java/jdk8u275/jre/lib/amd64/server/libjvm.so
#2  0x00007ffff67d6ba1 in LazyClassPathEntry::open_stream(char const*, Thread*) () from /usr/java/jdk8u275/jre/lib/amd64/server/libjvm.so
#3  0x00007ffff67d8b99 in ClassLoader::load_classfile(Symbol*, Thread*) () from /usr/java/jdk8u275/jre/lib/amd64/server/libjvm.so
#4  0x00007ffff6e32e9f in SystemDictionary::load_instance_class(Symbol*, Handle, Thread*) () from /usr/java/jdk8u275/jre/lib/amd64/server/libjvm.so
#5  0x00007ffff6e3397e in SystemDictionary::resolve_instance_class_or_null(Symbol*, Handle, Handle, Thread*) () from /usr/java/jdk8u275/jre/lib/amd64/server/libjvm.so
#6  0x00007ffff6e34f93 in SystemDictionary::initialize_wk_klasses_until(SystemDictionary::WKID, SystemDictionary::WKID&, Thread*) () from /usr/java/jdk8u275/jre/lib/amd64/server/libjvm.so
#7  0x00007ffff6e35165 in SystemDictionary::initialize_preloaded_classes(Thread*) () from /usr/java/jdk8u275/jre/lib/amd64/server/libjvm.so
#8  0x00007ffff6e355a8 in SystemDictionary::initialize(Thread*) () from /usr/java/jdk8u275/jre/lib/amd64/server/libjvm.so
#9  0x00007ffff6e84928 in Universe::genesis(Thread*) () from /usr/java/jdk8u275/jre/lib/amd64/server/libjvm.so
#10 0x00007ffff6e8596c in universe2_init() () from /usr/java/jdk8u275/jre/lib/amd64/server/libjvm.so
#11 0x00007ffff69d5248 in init_globals() () from /usr/java/jdk8u275/jre/lib/amd64/server/libjvm.so
#12 0x00007ffff6e6a38d in Threads::create_vm(JavaVMInitArgs*, bool*) () from /usr/java/jdk8u275/jre/lib/amd64/server/libjvm.so
#13 0x00007ffff6aae50f in JNI_CreateJavaVM () from /usr/java/jdk8u275/jre/lib/amd64/server/libjvm.so
#14 0x00007ffff79aefa0 in JavaMain () from /usr/java/jdk8u275/bin/../lib/amd64/jli/libjli.so
#15 0x00007ffff7bc6e65 in start_thread () from /lib64/libpthread.so.0
#16 0x00007ffff74d388d in clone () from /lib64/libc.so.6

在这里我们看到了确切的堆栈跟踪,JVM 首次打开的位置 rt.jar。这发生在 JVM bootstrap 期间,在初始化系统字典时预加载系统 class。

现在很容易在 source code.
中找到这些函数 classLoader.cpp 是一个很好的起点。