mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-19 18:44:38 +02:00
8255883: Avoid duplicated GeneratedMethodAccessor when reflect method invoked from different threads
Reviewed-by: shade, alanb
This commit is contained in:
parent
ac3948930e
commit
8eeb36f14a
2 changed files with 46 additions and 18 deletions
|
@ -28,14 +28,20 @@ package jdk.internal.reflect;
|
||||||
import sun.reflect.misc.ReflectUtil;
|
import sun.reflect.misc.ReflectUtil;
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
|
import jdk.internal.misc.Unsafe;
|
||||||
|
|
||||||
/** Used only for the first few invocations of a Constructor;
|
/** Used only for the first few invocations of a Constructor;
|
||||||
afterward, switches to bytecode-based implementation */
|
afterward, switches to bytecode-based implementation */
|
||||||
|
|
||||||
class NativeConstructorAccessorImpl extends ConstructorAccessorImpl {
|
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 final Constructor<?> c;
|
||||||
private DelegatingConstructorAccessorImpl parent;
|
private DelegatingConstructorAccessorImpl parent;
|
||||||
private int numInvocations;
|
private int numInvocations;
|
||||||
|
private volatile int generated;
|
||||||
|
|
||||||
NativeConstructorAccessorImpl(Constructor<?> c) {
|
NativeConstructorAccessorImpl(Constructor<?> c) {
|
||||||
this.c = c;
|
this.c = c;
|
||||||
|
@ -51,14 +57,22 @@ class NativeConstructorAccessorImpl extends ConstructorAccessorImpl {
|
||||||
// be found from the generated bytecode.
|
// be found from the generated bytecode.
|
||||||
if (++numInvocations > ReflectionFactory.inflationThreshold()
|
if (++numInvocations > ReflectionFactory.inflationThreshold()
|
||||||
&& !c.getDeclaringClass().isHidden()
|
&& !c.getDeclaringClass().isHidden()
|
||||||
&& !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) {
|
&& !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())
|
||||||
ConstructorAccessorImpl acc = (ConstructorAccessorImpl)
|
&& generated == 0
|
||||||
new MethodAccessorGenerator().
|
&& U.compareAndSetInt(this, GENERATED_OFFSET, 0, 1)) {
|
||||||
generateConstructor(c.getDeclaringClass(),
|
try {
|
||||||
c.getParameterTypes(),
|
ConstructorAccessorImpl acc = (ConstructorAccessorImpl)
|
||||||
c.getExceptionTypes(),
|
new MethodAccessorGenerator().
|
||||||
c.getModifiers());
|
generateConstructor(c.getDeclaringClass(),
|
||||||
parent.setDelegate(acc);
|
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);
|
return newInstance0(c, args);
|
||||||
|
|
|
@ -28,14 +28,20 @@ package jdk.internal.reflect;
|
||||||
import sun.reflect.misc.ReflectUtil;
|
import sun.reflect.misc.ReflectUtil;
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
|
import jdk.internal.misc.Unsafe;
|
||||||
|
|
||||||
/** Used only for the first few invocations of a Method; afterward,
|
/** Used only for the first few invocations of a Method; afterward,
|
||||||
switches to bytecode-based implementation */
|
switches to bytecode-based implementation */
|
||||||
|
|
||||||
class NativeMethodAccessorImpl extends MethodAccessorImpl {
|
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 final Method method;
|
||||||
private DelegatingMethodAccessorImpl parent;
|
private DelegatingMethodAccessorImpl parent;
|
||||||
private int numInvocations;
|
private int numInvocations;
|
||||||
|
private volatile int generated;
|
||||||
|
|
||||||
NativeMethodAccessorImpl(Method method) {
|
NativeMethodAccessorImpl(Method method) {
|
||||||
this.method = method;
|
this.method = method;
|
||||||
|
@ -49,16 +55,24 @@ class NativeMethodAccessorImpl extends MethodAccessorImpl {
|
||||||
// found from the generated bytecode.
|
// found from the generated bytecode.
|
||||||
if (++numInvocations > ReflectionFactory.inflationThreshold()
|
if (++numInvocations > ReflectionFactory.inflationThreshold()
|
||||||
&& !method.getDeclaringClass().isHidden()
|
&& !method.getDeclaringClass().isHidden()
|
||||||
&& !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
|
&& !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())
|
||||||
MethodAccessorImpl acc = (MethodAccessorImpl)
|
&& generated == 0
|
||||||
new MethodAccessorGenerator().
|
&& U.compareAndSetInt(this, GENERATED_OFFSET, 0, 1)) {
|
||||||
generateMethod(method.getDeclaringClass(),
|
try {
|
||||||
method.getName(),
|
MethodAccessorImpl acc = (MethodAccessorImpl)
|
||||||
method.getParameterTypes(),
|
new MethodAccessorGenerator().
|
||||||
method.getReturnType(),
|
generateMethod(method.getDeclaringClass(),
|
||||||
method.getExceptionTypes(),
|
method.getName(),
|
||||||
method.getModifiers());
|
method.getParameterTypes(),
|
||||||
parent.setDelegate(acc);
|
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);
|
return invoke0(method, obj, args);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue