8255883: Avoid duplicated GeneratedMethodAccessor when reflect method invoked from different threads
Reviewed-by: shade, alanb
This commit is contained in:
parent
ac3948930e
commit
8eeb36f14a
src/java.base/share/classes/jdk/internal/reflect
@ -28,14 +28,20 @@ package jdk.internal.reflect;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
/** Used only for the first few invocations of a Constructor;
|
||||
afterward, switches to bytecode-based implementation */
|
||||
|
||||
class NativeConstructorAccessorImpl extends ConstructorAccessorImpl {
|
||||
private static final Unsafe U = Unsafe.getUnsafe();
|
||||
private static final long GENERATED_OFFSET
|
||||
= U.objectFieldOffset(NativeConstructorAccessorImpl.class, "generated");
|
||||
|
||||
private final Constructor<?> c;
|
||||
private DelegatingConstructorAccessorImpl parent;
|
||||
private int numInvocations;
|
||||
private volatile int generated;
|
||||
|
||||
NativeConstructorAccessorImpl(Constructor<?> c) {
|
||||
this.c = c;
|
||||
@ -51,14 +57,22 @@ class NativeConstructorAccessorImpl extends ConstructorAccessorImpl {
|
||||
// be found from the generated bytecode.
|
||||
if (++numInvocations > ReflectionFactory.inflationThreshold()
|
||||
&& !c.getDeclaringClass().isHidden()
|
||||
&& !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) {
|
||||
ConstructorAccessorImpl acc = (ConstructorAccessorImpl)
|
||||
new MethodAccessorGenerator().
|
||||
generateConstructor(c.getDeclaringClass(),
|
||||
c.getParameterTypes(),
|
||||
c.getExceptionTypes(),
|
||||
c.getModifiers());
|
||||
parent.setDelegate(acc);
|
||||
&& !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())
|
||||
&& generated == 0
|
||||
&& U.compareAndSetInt(this, GENERATED_OFFSET, 0, 1)) {
|
||||
try {
|
||||
ConstructorAccessorImpl acc = (ConstructorAccessorImpl)
|
||||
new MethodAccessorGenerator().
|
||||
generateConstructor(c.getDeclaringClass(),
|
||||
c.getParameterTypes(),
|
||||
c.getExceptionTypes(),
|
||||
c.getModifiers());
|
||||
parent.setDelegate(acc);
|
||||
} catch (Throwable t) {
|
||||
// Throwable happens in generateConstructor, restore generated to 0
|
||||
generated = 0;
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
return newInstance0(c, args);
|
||||
|
@ -28,14 +28,20 @@ package jdk.internal.reflect;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
/** Used only for the first few invocations of a Method; afterward,
|
||||
switches to bytecode-based implementation */
|
||||
|
||||
class NativeMethodAccessorImpl extends MethodAccessorImpl {
|
||||
private static final Unsafe U = Unsafe.getUnsafe();
|
||||
private static final long GENERATED_OFFSET
|
||||
= U.objectFieldOffset(NativeMethodAccessorImpl.class, "generated");
|
||||
|
||||
private final Method method;
|
||||
private DelegatingMethodAccessorImpl parent;
|
||||
private int numInvocations;
|
||||
private volatile int generated;
|
||||
|
||||
NativeMethodAccessorImpl(Method method) {
|
||||
this.method = method;
|
||||
@ -49,16 +55,24 @@ class NativeMethodAccessorImpl extends MethodAccessorImpl {
|
||||
// found from the generated bytecode.
|
||||
if (++numInvocations > ReflectionFactory.inflationThreshold()
|
||||
&& !method.getDeclaringClass().isHidden()
|
||||
&& !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
|
||||
MethodAccessorImpl acc = (MethodAccessorImpl)
|
||||
new MethodAccessorGenerator().
|
||||
generateMethod(method.getDeclaringClass(),
|
||||
method.getName(),
|
||||
method.getParameterTypes(),
|
||||
method.getReturnType(),
|
||||
method.getExceptionTypes(),
|
||||
method.getModifiers());
|
||||
parent.setDelegate(acc);
|
||||
&& !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())
|
||||
&& generated == 0
|
||||
&& U.compareAndSetInt(this, GENERATED_OFFSET, 0, 1)) {
|
||||
try {
|
||||
MethodAccessorImpl acc = (MethodAccessorImpl)
|
||||
new MethodAccessorGenerator().
|
||||
generateMethod(method.getDeclaringClass(),
|
||||
method.getName(),
|
||||
method.getParameterTypes(),
|
||||
method.getReturnType(),
|
||||
method.getExceptionTypes(),
|
||||
method.getModifiers());
|
||||
parent.setDelegate(acc);
|
||||
} catch (Throwable t) {
|
||||
// Throwable happens in generateMethod, restore generated to 0
|
||||
generated = 0;
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
return invoke0(method, obj, args);
|
||||
|
Loading…
x
Reference in New Issue
Block a user