在documentation我找到了:
类对象由Java Virtual自动构造 通过调用defineClass方法加载机器作为类 在类加载器中。
我检查了the source code,但未找到要调用的地点defineClass
,例如来自loadClass方法。
你能告诉我,根据这个方案,谁和何时拨打defineClass
方法:
图片source
答案 0 :(得分:10)
在调用defineClass()
期间调用ClassLoader#loadClass()
方法。但是,这不是在java.lang.ClassLoader
类中直接完成的,而是在其子类中的一个,例如在URLClassLoader#findClass()
。
对ClassLoader#defineClass()
的调用最终会调用其中一个原生方法defineClass1()
或defineClass2()
。这些方法的C实现可以在src/share/native/java/lang/ClassLoader.c
中的OpenJDK中找到。
答案 1 :(得分:5)
java.lang.ClassLoader
是一个很大的课程。使用您的GrepCode链接(适用于java 6-b14版本),您可以在第267行找到公共loadClass
方法。
此方法在第308行调用受保护的loadClass
方法,此方法尝试使用以下方法加载previosly加载的类:
findLoadedClass
,最后调用Native方法,parent.loadClass
,findBootstrapClass0
(原生方法)如果没有parent
,findClass
如果找不到课程。这很重要,因为ClassLoader
会尝试重复已经加载的clases,请记住。
但是,defineClass
在哪里被调用?这个抽象类没有地方,但如果你使用GrepCode的参考工具并搜索它的使用位置defineClass
(see here results),你会发现很多具体的类最终调用{{1} }。
这不是直截了当的,其中一些类会覆盖definClass
,而其他类会调用自己的defineClass
,然后调用......等等,但最后它会调用loadClass
。< / p>
不要忘记defineClass
的{{1}}以三种本机方法之一结束,这些方法负责 JVM魔法:defineClass
,{{1} }和/或ClassLoader
原生函数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
希望它能回答你的问题。
答案 2 :(得分:1)
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
. . .
}
}