Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 17 additions & 24 deletions src/java.base/share/classes/java/lang/reflect/Constructor.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -88,26 +86,27 @@ private GenericsFactory getFactory() {
@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() {
Expand Down Expand Up @@ -143,13 +142,6 @@ Constructor<T> getRoot() {
* "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");

Expand All @@ -162,6 +154,7 @@ Constructor<T> copy() {
res.root = this;
// Might as well eagerly propagate this if already present
res.constructorAccessor = constructorAccessor;
res.genericInfo = genericInfo;
return res;
}

Expand Down
42 changes: 20 additions & 22 deletions src/java.base/share/classes/java/lang/reflect/Field.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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

Expand All @@ -107,17 +103,18 @@ private GenericsFactory getFactory() {
// 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
*/
Expand Down Expand Up @@ -162,6 +159,7 @@ Field copy() {
// Might as well eagerly propagate this if already present
res.fieldAccessor = fieldAccessor;
res.overrideFieldAccessor = overrideFieldAccessor;
res.genericInfo = genericInfo;

return res;
}
Expand Down
46 changes: 20 additions & 26 deletions src/java.base/share/classes/java/lang/reflect/Method.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;}
Expand All @@ -111,14 +109,16 @@ private GenericsFactory getFactory() {
@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;
}

/**
Expand Down Expand Up @@ -154,22 +154,16 @@ MethodRepository getGenericInfo() {
* "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");

Method res = new Method(clazz, name, parameterTypes, returnType,
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;
}

Expand Down