Exception in thread "main" java.lang.NoClassDefFoundError: sun/reflect/ConstructorAccessorImpl at sun.misc.Unsafe.defineClass(Native Method) at sun.reflect.ClassDefiner.defineClass(ClassDefiner.java:63) at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:399) at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:394) at java.security.AccessController.doPrivileged(Native Method) at sun.reflect.MethodAccessorGenerator.generate(MethodAccessorGenerator.java:393) at sun.reflect.MethodAccessorGenerator.generateConstructor(MethodAccessorGenerator.java:92) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:55) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at java.lang.Class.newInstance(Class.java:442) at com.thomas.classloader.unload.MonitorHotSwap.main(MonitorHotSwap.java:34) Caused by: java.lang.ClassNotFoundException: sun.reflect.ConstructorAccessorImpl at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ...
... [Loaded sun.reflect.DelegatingMethodAccessorImpl from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar] Hello, hello0 ... Hello, hello14 [Loaded sun.reflect.ClassFileConstants from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar] [Loaded sun.reflect.AccessorGenerator from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar] [Loaded sun.reflect.MethodAccessorGenerator from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar] [Loaded sun.reflect.ByteVectorFactory from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar] [Loaded sun.reflect.ByteVector from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar] [Loaded sun.reflect.ByteVectorImpl from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar] [Loaded sun.reflect.ClassFileAssembler from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar] [Loaded sun.reflect.UTF8 from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar] [Loaded sun.reflect.Label from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar] [Loaded sun.reflect.Label$PatchInfo from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar] [Loaded java.util.ArrayList$Itr from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar] [Loaded sun.reflect.MethodAccessorGenerator$1 from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar] [Loaded sun.reflect.ClassDefiner from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar] [Loaded sun.reflect.ClassDefiner$1 from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar] [Loaded sun.reflect.GeneratedMethodAccessor1 from __JVM_DefineClass__] Hello, hello15 Hello, hello16 Hello, hello17 [Loaded java.lang.Shutdown from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar] [Loaded java.lang.Shutdown$Lock from /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/rt.jar]
publicfinalclassMethodextendsExecutable { ... privatevolatile 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.) // // If this branching structure would ever contain cycles, deadlocks can // occur in annotation code. private Method root; @CallerSensitive public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!override) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { Class<?> caller = Reflection.getCallerClass(); checkAccess(caller, clazz, obj, modifiers); } } MethodAccessorma= methodAccessor; // read volatile if (ma == null) { ma = acquireMethodAccessor(); } return ma.invoke(obj, args); } private MethodAccessor acquireMethodAccessor() { // First check to see if one has been created yet, and take it // if so MethodAccessortmp=null; if (root != null) tmp = root.getMethodAccessor(); if (tmp != null) { methodAccessor = tmp; } else { // Otherwise fabricate one and propagate it up to the root tmp = reflectionFactory.newMethodAccessor(this); setMethodAccessor(tmp); } return tmp; } ... }
package sun.reflect; ... publicclassReflectionFactory { // "Inflation" mechanism. Loading bytecodes to implement // Method.invoke() and Constructor.newInstance() currently costs // 3-4x more than an invocation via native code for the first // invocation (though subsequent invocations have been benchmarked // to be over 20x faster). Unfortunately this cost increases // startup time for certain applications that use reflection // intensively (but only once per class) to bootstrap themselves. // To avoid this penalty we reuse the existing JVM entry points // for the first few invocations of Methods and Constructors and // then switch to the bytecode-based implementations. // // Package-private to be accessible to NativeMethodAccessorImpl // and NativeConstructorAccessorImpl privatestaticbooleannoInflation=false; privatestaticintinflationThreshold=15; ... public MethodAccessor newMethodAccessor(Method method) { checkInitted();
先来看NativeMethodAccessorImpl的invoke0,这是默认的逻辑,即ReflectionFactory提到的 Inflation, Loading bytecodes to implement Method.invoke() and Constructor.newInstance() currently costs 3-4x more than an invocation via native code for the first invocation (though subsequent invocations have been benchmarked to be over 20x faster). java bytecode版本运行快,但是初始化耗时,而native版本启动快,但若长久运行效率不如bytecode版本。 在有的文章里说,”调用JNI方法耗时“,如马化腾先生说的,这句话对也不对。因为这句话是没有指明的是耗时的究竟是“调用”这个操作还是“JNI方法”,而且这个“调用”指的是哪些(call,参数校验,java和C的参数/结果转换…)?不过还好平时基本不会用到,所以许多技术交流或者面试这么问这么答对的时候不会有什么大问题。 那么究竟是哪个耗时呢?事实上从下面这张火焰图可以明显看出来。
is a marker class in the hierarchy. All subclasses of this class are
"magically" granted access by the VM to otherwise inaccessible
fields and methods of other classes. It is used to hold the code
for dynamically-generated FieldAccessorImpl and MethodAccessorImpl
subclasses. (Use of the word "unsafe" was avoided in this class's
name to avoid confusion with {@link sun.misc.Unsafe}.)
这也表明了至少generate底层是支持invoke 到private方法的。 public Object invoke(final Object o, final Object[] array) 从这一句我们也可以看到,即便是GeneratedMethodAccessor1,这个Method的对象/参数/返回都退化成了Object,导致需要一些类型check,但这是由外层方法决定的,MethodHandle避免了这类问题。
voidJavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArguments* args, TRAPS) { methodHandle method = *m; JavaThread* thread = (JavaThread*)THREAD; assert(thread->is_Java_thread(), "must be called by a java thread"); assert(method.not_null(), "must have a method to call"); assert(!SafepointSynchronize::is_at_safepoint(), "call to Java code during VM operation"); assert(!thread->handle_area()->no_handle_mark_active(), "cannot call out to Java here"); ... // do call { JavaCallWrapper link(method, receiver, result, CHECK); { HandleMark hm(thread); // HandleMark used by HandleMarkCleaner
Returns the class of the caller of the method calling this method, ignoring frames associated with java.lang.reflect.Method.invoke() and its implementation
/** * Checks if {@code Class cls} is a VM-anonymous class * as defined by {@link sun.misc.Unsafe#defineAnonymousClass} * (not to be confused with a Java Language anonymous inner class). */ publicstaticbooleanisVMAnonymousClass(Class<?> cls) { return cls.getName().indexOf("/") > -1; }
// Bootstrapping issue: since we use Class.newInstance() in // the ConstructorAccessor generation process, we have to // break the cycle here. if (Reflection.isSubclassOf(declaringClass, ConstructorAccessorImpl.class)) { returnnewBootstrapConstructorAccessorImpl(c); }