public class A {
public void foo(String name) {
System.out.println("Hello, " + name);
}
}
可以编写另外一个类来反射调用A上的方法:
import java.lang.reflect.Method;
public class TestClassLoad {
public static void main(String[] args) throws Exception {
Class<?> clz = Class.forName("A");
Object o = clz.newInstance();
Method m = clz.getMethod("foo", String.class);
for (int i = 0; i < 16; i++) {
m.invoke(o, Integer.toString(i));
}
}
}
注意到TestClassLoad类上不会有对类A的符号依赖——也就是说在加载并初始化TestClassLoad类时不需要关心类A的存在与否,而是等到main()方法执行到调用Class.forName()时才试图对类A做动态加载;这里用的是一个参数版的forName(),也就是使用当前方法所在类的ClassLoader来加载,并且初始化新加载的类。……好吧这个细节跟主题没啥关系。
回到主题。这次我的测试环境是Sun的JDK 1.6.0 update 13 build 03。编译上述代码,并在执行TestClassLoad时加入-XX:+TraceClassLoading参数(或者-verbose:class或者直接-verbose都行),如下:
[Loaded TestClassLoad from file:/D:/temp_code/test_java_classload/] [Loaded A from file:/D:/temp_code/test_java_classload/] [Loaded sun.reflect.NativeMethodAccessorImpl from shared objects file] [Loaded sun.reflect.DelegatingMethodAccessorImpl from shared objects file] Hello, 0 Hello, 1 Hello, 2 Hello, 3 Hello, 4 Hello, 5 Hello, 6 Hello, 7 Hello, 8 Hello, 9 Hello, 10 Hello, 11 Hello, 12 Hello, 13 Hello, 14 [Loaded sun.reflect.ClassFileConstants from shared objects file] [Loaded sun.reflect.AccessorGenerator from shared objects file] [Loaded sun.reflect.MethodAccessorGenerator from shared objects file] [Loaded sun.reflect.ByteVectorFactory from shared objects file] [Loaded sun.reflect.ByteVector from shared objects file] [Loaded sun.reflect.ByteVectorImpl from shared objects file] [Loaded sun.reflect.ClassFileAssembler from shared objects file] [Loaded sun.reflect.UTF8 from shared objects file] [Loaded java.lang.Void from shared objects file] [Loaded sun.reflect.Label from shared objects file] [Loaded sun.reflect.Label$PatchInfo from shared objects file] [Loaded java.util.AbstractList$Itr from shared objects file] [Loaded sun.reflect.MethodAccessorGenerator$1 from shared objects file] [Loaded sun.reflect.ClassDefiner from shared objects file] [Loaded sun.reflect.ClassDefiner$1 from shared objects file] [Loaded sun.reflect.GeneratedMethodAccessor1 from __JVM_DefineClass__] Hello, 15
可以看到前15次反射调用A.foo()方法并没有什么稀奇的地方,但在第16次反射调用时似乎有什么东西被触发了,导致JVM新加载了一堆类,其中就包括[Loaded sun.reflect.GeneratedMethodAccessor1 from __JVM_DefineClass__]这么一行。这是哪里来的呢?
先来看看JDK里Method.invoke()是怎么实现的。
java.lang.reflect.Method:
public final class Method extends AccessibleObject implements GenericDeclaration, Member { // ... private volatile MethodAccessor methodAccessor; // For sharing of MethodAccessors. This branching structure is // currently only two levels deep (i.e., one root Method and // potentially many Method objects pointing to it.) private Method root; // ... public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!override) { if (!Reflection.quickCheckMemberAccess(clazz, modi


2万+

被折叠的 条评论
为什么被折叠?



