在documentation中,我发现:
类对象是由Java Virtual Machine在加载类时自动构造的,并通过调用类加载器中的defineClass方法来实现。
我检查了the source code,但没有找到要调用的地方defineClass
,例如从loadClass方法。您能告诉我,根据这个方案,谁在什么时候调用defineClass
方法吗?
图片
发布于 2015-12-06 17:14:46
在调用ClassLoader#loadClass()
期间调用defineClass()
方法。然而,这不是直接在java.lang.ClassLoader
类中完成的,而是在它的一个子类中完成的,例如在URLClassLoader#findClass()
中。
对ClassLoader#defineClass()
的调用以对本机方法defineClass1()
或defineClass2()
之一的调用结束。这些方法的C实现可以在src/share/native/java/lang/ClassLoader.c
的OpenJDK中找到。
发布于 2015-12-06 17:35:48
java.lang.ClassLoader
是一个很大的类。使用您的GrepCode链接(用于Java6-b14版本),您可以在第267行找到公共loadClass
方法。
此方法在第308行调用受保护的loadClass
方法,此方法尝试使用以下命令加载先前加载的类:
findLoadedClass
最终调用本机方法,parent.loadClass
,如果没有parent
,则调用findClass
(也是本机方法)。这一点很重要,因为ClassLoader
试图重用已经加载的类,请记住。
但是,在哪里调用defineClass
呢?这个抽象类没有位置,但是如果你使用GrepCode的引用工具并搜索它在哪里使用defineClass
(see here results),你会发现很多具体的类,它们最终调用了definClass
。
这并不简单,其中一些类覆盖defineClass
,而其他类调用自己的loadClass
,然后调用...以此类推,但最后它调用了defineClass
。
不要忘记,ClassLoader
的defineClass
以以下三个本机方法之一结束:defineClass0
、defineClass1
和/或defineClass2
编辑
本机函数defineClass0
从ClassLoader.c
调用Java_java_lang_ClassLoader_defineClass0
,对于1和2函数也是如此。
此函数使用在jvm.h
中定义并在openjdk\hotspot\src\share\vm\prims\jvm.cpp
中实现的JVM_DefineClassWithSource
创建所需的类。
最后一个文件定义了jvm_define_class_common
函数,它最终是创建所需类的函数。最后,此函数调用JNIHandles::make_local
来分配类。您可以在openjdk\hotspot\src\share\vm\runtime\jniHandles.cpp
中查看最后一个函数的代码
希望它能回答你的问题。
发布于 2015-12-12 13:04:03
class NetworkClassLoader extends ClassLoader {
String host;
int port;
public Class findClass(String name) {
byte[] b = loadClassData(name);
return defineClass(name, b, 0, b.length);
}
private byte[] loadClassData(String name) {
// load the class data from the connection
. . .
}
}
https://stackoverflow.com/questions/34070594
复制相似问题