8336267: Method and Constructor signature parsing can be shared on the root object
Reviewed-by: mchung
This commit is contained in:
parent
1f7d524fd3
commit
8d6cfba37f
src/java.base/share/classes/java/lang/reflect
@ -72,8 +72,6 @@ public final class Constructor<T> extends Executable {
|
||||
private final int modifiers;
|
||||
// Generics and annotations support
|
||||
private final transient String signature;
|
||||
// generic info repository; lazily initialized
|
||||
private transient volatile ConstructorRepository genericInfo;
|
||||
private final byte[] annotations;
|
||||
private final byte[] parameterAnnotations;
|
||||
|
||||
@ -88,26 +86,27 @@ public final class Constructor<T> extends Executable {
|
||||
@Override
|
||||
ConstructorRepository getGenericInfo() {
|
||||
var genericInfo = this.genericInfo;
|
||||
// lazily initialize repository if necessary
|
||||
if (genericInfo == null) {
|
||||
// create and cache generic info repository
|
||||
genericInfo =
|
||||
ConstructorRepository.make(getSignature(),
|
||||
getFactory());
|
||||
var root = this.root;
|
||||
if (root != null) {
|
||||
genericInfo = root.getGenericInfo();
|
||||
} else {
|
||||
genericInfo = ConstructorRepository.make(getSignature(), getFactory());
|
||||
}
|
||||
this.genericInfo = genericInfo;
|
||||
}
|
||||
return genericInfo; //return cached repository
|
||||
return genericInfo;
|
||||
}
|
||||
|
||||
@Stable
|
||||
private ConstructorAccessor constructorAccessor;
|
||||
// For sharing of ConstructorAccessors. This branching structure
|
||||
// is currently only two levels deep (i.e., one root Constructor
|
||||
// and potentially many Constructor objects pointing to it.)
|
||||
//
|
||||
// If this branching structure would ever contain cycles, deadlocks can
|
||||
// occur in annotation code.
|
||||
private Constructor<T> root;
|
||||
/**
|
||||
* Constructors are mutable due to {@link AccessibleObject#setAccessible(boolean)}.
|
||||
* Thus, we return a new copy of a root each time a constructor is returned.
|
||||
* Some lazily initialized immutable states can be stored on root and shared to the copies.
|
||||
*/
|
||||
private Constructor<T> root;
|
||||
private transient volatile ConstructorRepository genericInfo;
|
||||
private @Stable ConstructorAccessor constructorAccessor;
|
||||
// End shared states
|
||||
|
||||
@Override
|
||||
Constructor<T> getRoot() {
|
||||
@ -143,13 +142,6 @@ public final class Constructor<T> extends Executable {
|
||||
* "root" field points to this Constructor.
|
||||
*/
|
||||
Constructor<T> copy() {
|
||||
// This routine enables sharing of ConstructorAccessor objects
|
||||
// among Constructor objects which refer to the same underlying
|
||||
// method in the VM. (All of this contortion is only necessary
|
||||
// because of the "accessibility" bit in AccessibleObject,
|
||||
// which implicitly requires that new java.lang.reflect
|
||||
// objects be fabricated for each reflective call on Class
|
||||
// objects.)
|
||||
if (this.root != null)
|
||||
throw new IllegalArgumentException("Can not copy a non-root Constructor");
|
||||
|
||||
@ -162,6 +154,7 @@ public final class Constructor<T> extends Executable {
|
||||
res.root = this;
|
||||
// Might as well eagerly propagate this if already present
|
||||
res.constructorAccessor = constructorAccessor;
|
||||
res.genericInfo = genericInfo;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -76,22 +76,18 @@ class Field extends AccessibleObject implements Member {
|
||||
private final boolean trustedFinal;
|
||||
// Generics and annotations support
|
||||
private final transient String signature;
|
||||
// generic info repository; lazily initialized
|
||||
private transient volatile FieldRepository genericInfo;
|
||||
private final byte[] annotations;
|
||||
// Cached field accessor created without override
|
||||
@Stable
|
||||
private FieldAccessor fieldAccessor;
|
||||
// Cached field accessor created with override
|
||||
@Stable
|
||||
private FieldAccessor overrideFieldAccessor;
|
||||
// For sharing of FieldAccessors. This branching structure is
|
||||
// currently only two levels deep (i.e., one root Field and
|
||||
// potentially many Field objects pointing to it.)
|
||||
//
|
||||
// If this branching structure would ever contain cycles, deadlocks can
|
||||
// occur in annotation code.
|
||||
private Field root;
|
||||
|
||||
/**
|
||||
* Fields are mutable due to {@link AccessibleObject#setAccessible(boolean)}.
|
||||
* Thus, we return a new copy of a root each time a field is returned.
|
||||
* Some lazily initialized immutable states can be stored on root and shared to the copies.
|
||||
*/
|
||||
private Field root;
|
||||
private transient volatile FieldRepository genericInfo;
|
||||
private @Stable FieldAccessor fieldAccessor; // access control enabled
|
||||
private @Stable FieldAccessor overrideFieldAccessor; // access control suppressed
|
||||
// End shared states
|
||||
|
||||
// Generics infrastructure
|
||||
|
||||
@ -107,17 +103,18 @@ class Field extends AccessibleObject implements Member {
|
||||
// Accessor for generic info repository
|
||||
private FieldRepository getGenericInfo() {
|
||||
var genericInfo = this.genericInfo;
|
||||
// lazily initialize repository if necessary
|
||||
if (genericInfo == null) {
|
||||
// create and cache generic info repository
|
||||
genericInfo = FieldRepository.make(getGenericSignature(),
|
||||
getFactory());
|
||||
var root = this.root;
|
||||
if (root != null) {
|
||||
genericInfo = root.getGenericInfo();
|
||||
} else {
|
||||
genericInfo = FieldRepository.make(getGenericSignature(), getFactory());
|
||||
}
|
||||
this.genericInfo = genericInfo;
|
||||
}
|
||||
return genericInfo; //return cached repository
|
||||
return genericInfo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Package-private constructor
|
||||
*/
|
||||
@ -162,6 +159,7 @@ class Field extends AccessibleObject implements Member {
|
||||
// Might as well eagerly propagate this if already present
|
||||
res.fieldAccessor = fieldAccessor;
|
||||
res.overrideFieldAccessor = overrideFieldAccessor;
|
||||
res.genericInfo = genericInfo;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -81,22 +81,20 @@ public final class Method extends Executable {
|
||||
private final int modifiers;
|
||||
// Generics and annotations support
|
||||
private final transient String signature;
|
||||
// generic info repository; lazily initialized
|
||||
private transient volatile MethodRepository genericInfo;
|
||||
private final byte[] annotations;
|
||||
private final byte[] parameterAnnotations;
|
||||
private final byte[] annotationDefault;
|
||||
@Stable
|
||||
private 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;
|
||||
// Hash code of this object
|
||||
private int hash;
|
||||
|
||||
/**
|
||||
* Methods are mutable due to {@link AccessibleObject#setAccessible(boolean)}.
|
||||
* Thus, we return a new copy of a root each time a method is returned.
|
||||
* Some lazily initialized immutable states can be stored on root and shared to the copies.
|
||||
*/
|
||||
private Method root;
|
||||
private transient volatile MethodRepository genericInfo;
|
||||
private @Stable MethodAccessor methodAccessor;
|
||||
// End shared states
|
||||
private int hash; // not shared right now, eligible if expensive
|
||||
|
||||
// Generics infrastructure
|
||||
private String getGenericSignature() {return signature;}
|
||||
@ -111,14 +109,16 @@ public final class Method extends Executable {
|
||||
@Override
|
||||
MethodRepository getGenericInfo() {
|
||||
var genericInfo = this.genericInfo;
|
||||
// lazily initialize repository if necessary
|
||||
if (genericInfo == null) {
|
||||
// create and cache generic info repository
|
||||
genericInfo = MethodRepository.make(getGenericSignature(),
|
||||
getFactory());
|
||||
var root = this.root;
|
||||
if (root != null) {
|
||||
genericInfo = root.getGenericInfo();
|
||||
} else {
|
||||
genericInfo = MethodRepository.make(getGenericSignature(), getFactory());
|
||||
}
|
||||
this.genericInfo = genericInfo;
|
||||
}
|
||||
return genericInfo; //return cached repository
|
||||
return genericInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -154,13 +154,6 @@ public final class Method extends Executable {
|
||||
* "root" field points to this Method.
|
||||
*/
|
||||
Method copy() {
|
||||
// This routine enables sharing of MethodAccessor objects
|
||||
// among Method objects which refer to the same underlying
|
||||
// method in the VM. (All of this contortion is only necessary
|
||||
// because of the "accessibility" bit in AccessibleObject,
|
||||
// which implicitly requires that new java.lang.reflect
|
||||
// objects be fabricated for each reflective call on Class
|
||||
// objects.)
|
||||
if (this.root != null)
|
||||
throw new IllegalArgumentException("Can not copy a non-root Method");
|
||||
|
||||
@ -168,8 +161,9 @@ public final class Method extends Executable {
|
||||
exceptionTypes, modifiers, slot, signature,
|
||||
annotations, parameterAnnotations, annotationDefault);
|
||||
res.root = this;
|
||||
// Might as well eagerly propagate this if already present
|
||||
// Propagate shared states
|
||||
res.methodAccessor = methodAccessor;
|
||||
res.genericInfo = genericInfo;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user