28
28
import sun .reflect .misc .ReflectUtil ;
29
29
30
30
import java .lang .reflect .*;
31
+ import jdk .internal .misc .Unsafe ;
31
32
32
33
/** Used only for the first few invocations of a Method; afterward,
33
34
switches to bytecode-based implementation */
34
35
35
36
class NativeMethodAccessorImpl extends MethodAccessorImpl {
37
+ private static final Unsafe U = Unsafe .getUnsafe ();
38
+ private static final long GENERATED_OFFSET
39
+ = U .objectFieldOffset (NativeMethodAccessorImpl .class , "generated" );
40
+
36
41
private final Method method ;
37
42
private DelegatingMethodAccessorImpl parent ;
38
43
private int numInvocations ;
44
+ private volatile int generated ;
39
45
40
46
NativeMethodAccessorImpl (Method method ) {
41
47
this .method = method ;
@@ -49,16 +55,24 @@ public Object invoke(Object obj, Object[] args)
49
55
// found from the generated bytecode.
50
56
if (++numInvocations > ReflectionFactory .inflationThreshold ()
51
57
&& !method .getDeclaringClass ().isHidden ()
52
- && !ReflectUtil .isVMAnonymousClass (method .getDeclaringClass ())) {
53
- MethodAccessorImpl acc = (MethodAccessorImpl )
54
- new MethodAccessorGenerator ().
55
- generateMethod (method .getDeclaringClass (),
56
- method .getName (),
57
- method .getParameterTypes (),
58
- method .getReturnType (),
59
- method .getExceptionTypes (),
60
- method .getModifiers ());
61
- parent .setDelegate (acc );
58
+ && !ReflectUtil .isVMAnonymousClass (method .getDeclaringClass ())
59
+ && generated == 0
60
+ && U .compareAndSetInt (this , GENERATED_OFFSET , 0 , 1 )) {
61
+ try {
62
+ MethodAccessorImpl acc = (MethodAccessorImpl )
63
+ new MethodAccessorGenerator ().
64
+ generateMethod (method .getDeclaringClass (),
65
+ method .getName (),
66
+ method .getParameterTypes (),
67
+ method .getReturnType (),
68
+ method .getExceptionTypes (),
69
+ method .getModifiers ());
70
+ parent .setDelegate (acc );
71
+ } catch (Throwable t ) {
72
+ // Throwable happens in generateMethod, restore generated to 0
73
+ generated = 0 ;
74
+ throw t ;
75
+ }
62
76
}
63
77
64
78
return invoke0 (method , obj , args );
0 commit comments