在我发现的文档中:
类对象由Java虚拟机在加载类时自动构造,并通过调用类加载器中的defineClass方法来构造.
我检查了源代码,但没有找到defineClass
要调用的地方,例如来自loadClass方法.你能告诉我,defineClass
根据这个方案,谁和什么时候打电话的方法:
图片来源
defineClass()
在调用期间调用该方法ClassLoader#loadClass()
.但是,这不是在java.lang.ClassLoader
类中直接完成,而是在其子类之一中完成,例如在URLClassLoader#findClass()
.
调用ClassLoader#defineClass()
最终会调用其中一个本机方法defineClass1()
或defineClass2()
.这些方法的C实现可以在OpenJDK中找到src/share/native/java/lang/ClassLoader.c
.
java.lang.ClassLoader
是一个如此大的阶级.使用GrepCode链接(适用于java 6-b14版本),您可以在第267行找到公共loadClass
方法.
此方法loadClass
在第308行调用受保护的方法,此方法尝试使用以下方法加载previosly加载的类:
findLoadedClass
最后调用Native方法,
打电话parent.loadClass
,
findBootstrapClass0
(如果没有本地方法)parent
,
最后,findClass
如果没有找到课程.
这很重要,因为ClassLoader
请记住尝试重用已经加载的clases.
但是,在哪里被defineClass
调用?这个抽象类没有位置,但是如果你使用GrepCode的参考工具并搜索它的使用位置defineClass
(参见这里的结果),你会发现很多具体的类最终调用definClass
.
它并不简单,其中一些类会覆盖,defineClass
而其他类会调用它自己loadClass
然后调用...等等,但最后它会调用defineClass
.
不要忘记defineClass
的ClassLoader
两端三种本地方法是负责的一个JVM魔术:defineClass0
,defineClass1
和/或defineClass2
本机函数从1和2函数defineClass0
调用和相同.Java_java_lang_ClassLoader_defineClass0
ClassLoader.c
此函数使用JVM_DefineClassWithSource
在中定义jvm.h
和实现的内容创建所需的类openjdk\hotspot\src\share\vm\prims\jvm.cpp
.
最后一个文件定义了jvm_define_class_common
函数,它最终是创建所需类的函数.最后,这个函数调用JNIHandles::make_local
分配类.你可以看到最后一个函数的代码openjdk\hotspot\src\share\vm\runtime\jniHandles.cpp
希望它能回答你的问题.