34
34
switches to bytecode-based implementation */
35
35
36
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
+
37
41
private final Method method ;
38
42
private DelegatingMethodAccessorImpl parent ;
39
43
private int numInvocations ;
44
+ private volatile int generated ;
40
45
41
46
NativeMethodAccessorImpl (Method method ) {
42
47
this .method = method ;
@@ -48,27 +53,34 @@ public Object invoke(Object obj, Object[] args)
48
53
// We can't inflate methods belonging to vm-anonymous classes because
49
54
// that kind of class can't be referred to by name, hence can't be
50
55
// found from the generated bytecode.
51
- if ((++numInvocations > ReflectionFactory .inflationThreshold ()
52
- || Thread .currentThread ().isVirtual ())
53
- && !method .getDeclaringClass ().isHidden ()
54
- && !ReflectUtil .isVMAnonymousClass (method .getDeclaringClass ())) {
56
+ if (!method .getDeclaringClass ().isHidden ()
57
+ && !ReflectUtil .isVMAnonymousClass (method .getDeclaringClass ())
58
+ && (Thread .currentThread ().isVirtual ()
59
+ || (++numInvocations > ReflectionFactory .inflationThreshold ()
60
+ && (generated == 0 )
61
+ && U .compareAndSetInt (this , GENERATED_OFFSET , 0 , 1 )))) {
55
62
56
63
// class initializer may not have run
57
64
Unsafe .getUnsafe ().ensureClassInitialized (method .getDeclaringClass ());
58
65
59
66
MethodAccessorImpl acc ;
60
- if ( Reflection . isCallerSensitive ( method )) {
67
+ try {
61
68
// use bytecode generated implementation for @CS methods for now
62
- 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
- } else {
71
- acc = NewAccessorImplFactory .newMethodAccessorImpl (method );
69
+ if (Reflection .isCallerSensitive (method )) {
70
+ acc = (MethodAccessorImpl ) new MethodAccessorGenerator ()
71
+ .generateMethod (method .getDeclaringClass (),
72
+ method .getName (),
73
+ method .getParameterTypes (),
74
+ method .getReturnType (),
75
+ method .getExceptionTypes (),
76
+ method .getModifiers ());
77
+ } else {
78
+ acc = NewAccessorImplFactory .newMethodAccessorImpl (method );
79
+ }
80
+ } catch (Throwable t ) {
81
+ // generateMethod/newMethodAccessorImpl failed, restore generated to 0
82
+ generated = 0 ;
83
+ throw t ;
72
84
}
73
85
74
86
parent .setDelegate (acc );
0 commit comments