mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8266670: Better modeling of access flags in core reflection
Reviewed-by: mchung, rriggs, asotona
This commit is contained in:
parent
a5c25d8837
commit
de7467146f
14 changed files with 1480 additions and 16 deletions
|
@ -36,6 +36,7 @@ import java.io.InputStream;
|
|||
import java.io.ObjectStreamField;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.lang.reflect.AccessFlag;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Executable;
|
||||
|
@ -1312,6 +1313,7 @@ public final class Class<T> implements java.io.Serializable,
|
|||
*
|
||||
* @return the {@code int} representing the modifiers for this class
|
||||
* @see java.lang.reflect.Modifier
|
||||
* @see #accessFlags()
|
||||
* @see <a
|
||||
* href="{@docRoot}/java.base/java/lang/reflect/package-summary.html#LanguageJvmModel">Java
|
||||
* programming language and JVM modeling in core reflection</a>
|
||||
|
@ -1322,6 +1324,39 @@ public final class Class<T> implements java.io.Serializable,
|
|||
@IntrinsicCandidate
|
||||
public native int getModifiers();
|
||||
|
||||
/**
|
||||
* {@return an unmodifiable set of the {@linkplain AccessFlag access
|
||||
* flags} for this class, possibly empty}
|
||||
*
|
||||
* <p> If the underlying class is an array class, then its
|
||||
* {@code PUBLIC}, {@code PRIVATE} and {@code PROTECTED}
|
||||
* access flags are the same as those of its component type. If this
|
||||
* {@code Class} object represents a primitive type or void, the
|
||||
* {@code PUBLIC} access flag is present, and the
|
||||
* {@code PROTECTED} and {@code PRIVATE} access flags are always
|
||||
* absent. If this {@code Class} object represents an array class, a
|
||||
* primitive type or void, then the {@code FINAL} access flag is always
|
||||
* present and the interface access flag is always
|
||||
* absent. The values of its other access flags are not determined
|
||||
* by this specification.
|
||||
*
|
||||
* @see #getModifiers()
|
||||
* @jvms 4.1 The ClassFile Structure
|
||||
* @jvms 4.7.6 The InnerClasses Attribute
|
||||
* @since 20
|
||||
*/
|
||||
public Set<AccessFlag> accessFlags() {
|
||||
// This likely needs some refinement. Exploration of hidden
|
||||
// classes, array classes. Location.CLASS allows SUPER and
|
||||
// AccessFlag.MODULE which INNER_CLASS forbids. INNER_CLASS
|
||||
// allows PRIVATE, PROTECTED, and STATIC, which are not
|
||||
// allowed on Location.CLASS.
|
||||
return AccessFlag.maskToAccessFlags(getModifiers(),
|
||||
(isMemberClass() || isLocalClass() ||
|
||||
isAnonymousClass() || isArray()) ?
|
||||
AccessFlag.Location.INNER_CLASS :
|
||||
AccessFlag.Location.CLASS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the signers of this class.
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.io.InputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.reflect.AccessFlag;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
|
@ -105,7 +106,7 @@ public class ModuleDescriptor
|
|||
* An open module. An open module does not declare any open packages
|
||||
* but the resulting module is treated as if all packages are open.
|
||||
*/
|
||||
OPEN,
|
||||
OPEN(AccessFlag.OPEN.mask()),
|
||||
|
||||
/**
|
||||
* An automatic module. An automatic module is treated as if it exports
|
||||
|
@ -114,19 +115,24 @@ public class ModuleDescriptor
|
|||
* @apiNote This modifier does not correspond to a module flag in the
|
||||
* binary form of a module declaration ({@code module-info.class}).
|
||||
*/
|
||||
AUTOMATIC,
|
||||
AUTOMATIC(0 /* no flag per above comment */),
|
||||
|
||||
/**
|
||||
* The module was not explicitly or implicitly declared.
|
||||
*/
|
||||
SYNTHETIC,
|
||||
SYNTHETIC(AccessFlag.SYNTHETIC.mask()),
|
||||
|
||||
/**
|
||||
* The module was implicitly declared.
|
||||
*/
|
||||
MANDATED;
|
||||
}
|
||||
MANDATED(AccessFlag.MANDATED.mask());
|
||||
|
||||
private final int mask;
|
||||
private Modifier(int mask) {
|
||||
this.mask = mask;
|
||||
}
|
||||
private int mask() {return mask;}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> A dependence upon a module. </p>
|
||||
|
@ -152,28 +158,31 @@ public class ModuleDescriptor
|
|||
* module</i> to have an implicitly declared dependence on the module
|
||||
* named by the {@code Requires}.
|
||||
*/
|
||||
TRANSITIVE,
|
||||
TRANSITIVE(AccessFlag.TRANSITIVE.mask()),
|
||||
|
||||
/**
|
||||
* The dependence is mandatory in the static phase, during compilation,
|
||||
* but is optional in the dynamic phase, during execution.
|
||||
*/
|
||||
STATIC,
|
||||
STATIC(AccessFlag.STATIC_PHASE.mask()),
|
||||
|
||||
/**
|
||||
* The dependence was not explicitly or implicitly declared in the
|
||||
* source of the module declaration.
|
||||
*/
|
||||
SYNTHETIC,
|
||||
SYNTHETIC(AccessFlag.SYNTHETIC.mask()),
|
||||
|
||||
/**
|
||||
* The dependence was implicitly declared in the source of the module
|
||||
* declaration.
|
||||
*/
|
||||
MANDATED;
|
||||
|
||||
MANDATED(AccessFlag.MANDATED.mask());
|
||||
private final int mask;
|
||||
private Modifier(int mask) {
|
||||
this.mask = mask;
|
||||
}
|
||||
private int mask() {return mask;}
|
||||
}
|
||||
|
||||
private final Set<Modifier> mods;
|
||||
private final String name;
|
||||
private final Version compiledVersion;
|
||||
|
@ -203,6 +212,21 @@ public class ModuleDescriptor
|
|||
return mods;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return an unmodifiable set of the module {@linkplain AccessFlag
|
||||
* requires flags, possibly empty}}
|
||||
* @see #modifiers()
|
||||
* @jvms 4.7.25 The Module Attribute
|
||||
* @since 20
|
||||
*/
|
||||
public Set<AccessFlag> accessFlags() {
|
||||
int mask = 0;
|
||||
for (var modifier : mods) {
|
||||
mask |= modifier.mask();
|
||||
}
|
||||
return AccessFlag.maskToAccessFlags(mask, AccessFlag.Location.MODULE_REQUIRES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the module name.
|
||||
*
|
||||
|
@ -376,14 +400,19 @@ public class ModuleDescriptor
|
|||
* The export was not explicitly or implicitly declared in the
|
||||
* source of the module declaration.
|
||||
*/
|
||||
SYNTHETIC,
|
||||
SYNTHETIC(AccessFlag.SYNTHETIC.mask()),
|
||||
|
||||
/**
|
||||
* The export was implicitly declared in the source of the module
|
||||
* declaration.
|
||||
*/
|
||||
MANDATED;
|
||||
MANDATED(AccessFlag.MANDATED.mask());
|
||||
|
||||
private final int mask;
|
||||
private Modifier(int mask) {
|
||||
this.mask = mask;
|
||||
}
|
||||
private int mask() {return mask;}
|
||||
}
|
||||
|
||||
private final Set<Modifier> mods;
|
||||
|
@ -417,6 +446,21 @@ public class ModuleDescriptor
|
|||
return mods;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return an unmodifiable set of the module {@linkplain AccessFlag
|
||||
* export flags} for this module descriptor, possibly empty}
|
||||
* @see #modifiers()
|
||||
* @jvms 4.7.25 The Module Attribute
|
||||
* @since 20
|
||||
*/
|
||||
public Set<AccessFlag> accessFlags() {
|
||||
int mask = 0;
|
||||
for (var modifier : mods) {
|
||||
mask |= modifier.mask();
|
||||
}
|
||||
return AccessFlag.maskToAccessFlags(mask, AccessFlag.Location.MODULE_EXPORTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this is a qualified export.
|
||||
*
|
||||
|
@ -579,14 +623,18 @@ public class ModuleDescriptor
|
|||
* The open package was not explicitly or implicitly declared in
|
||||
* the source of the module declaration.
|
||||
*/
|
||||
SYNTHETIC,
|
||||
SYNTHETIC(AccessFlag.SYNTHETIC.mask()),
|
||||
|
||||
/**
|
||||
* The open package was implicitly declared in the source of the
|
||||
* module declaration.
|
||||
*/
|
||||
MANDATED;
|
||||
|
||||
MANDATED(AccessFlag.MANDATED.mask());
|
||||
private final int mask;
|
||||
private Modifier(int mask) {
|
||||
this.mask = mask;
|
||||
}
|
||||
private int mask() {return mask;}
|
||||
}
|
||||
|
||||
private final Set<Modifier> mods;
|
||||
|
@ -620,6 +668,21 @@ public class ModuleDescriptor
|
|||
return mods;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return an unmodifiable set of the module {@linkplain AccessFlag
|
||||
* opens flags}, possibly empty}
|
||||
* @see #modifiers()
|
||||
* @jvms 4.7.25 The Module Attribute
|
||||
* @since 20
|
||||
*/
|
||||
public Set<AccessFlag> accessFlags() {
|
||||
int mask = 0;
|
||||
for (var modifier : mods) {
|
||||
mask |= modifier.mask();
|
||||
}
|
||||
return AccessFlag.maskToAccessFlags(mask, AccessFlag.Location.MODULE_OPENS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this is a qualified {@code Opens}.
|
||||
*
|
||||
|
@ -1290,6 +1353,21 @@ public class ModuleDescriptor
|
|||
return modifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return an unmodifiable set of the {@linkplain AccessFlag
|
||||
* module flags}, possibly empty}
|
||||
* @see #modifiers()
|
||||
* @jvms 4.7.25 The Module Attribute
|
||||
* @since 20
|
||||
*/
|
||||
public Set<AccessFlag> accessFlags() {
|
||||
int mask = 0;
|
||||
for (var modifier : modifiers) {
|
||||
mask |= modifier.mask();
|
||||
}
|
||||
return AccessFlag.maskToAccessFlags(mask, AccessFlag.Location.MODULE);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Returns {@code true} if this is an open module. </p>
|
||||
*
|
||||
|
|
447
src/java.base/share/classes/java/lang/reflect/AccessFlag.java
Normal file
447
src/java.base/share/classes/java/lang/reflect/AccessFlag.java
Normal file
|
@ -0,0 +1,447 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 2022, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.lang.reflect;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import static java.util.Map.entry;
|
||||
|
||||
/**
|
||||
* Represents a JVM access or module-related flag on a runtime member,
|
||||
* such as a {@linkplain Class class}, {@linkplain Field field}, or
|
||||
* {@linkplain Executable method}.
|
||||
*
|
||||
* <P>JVM access and module-related flags are related to, but distinct
|
||||
* from Java language {@linkplain Modifier modifiers}. Some modifiers
|
||||
* and access flags have a one-to-one correspondence, such as {@code
|
||||
* public}. In other cases, some language-level modifiers do
|
||||
* <em>not</em> have an access flag, such as {@code sealed} (JVMS
|
||||
* {@jvms 4.7.31}) and some access flags have no corresponding
|
||||
* modifier, such as {@linkplain #SYNTHETIC synthetic}.
|
||||
*
|
||||
* <p>The values for the constants representing the access and module
|
||||
* flags are taken from sections of <cite>The Java Virtual Machine
|
||||
* Specification</cite> including {@jvms 4.1} (class access and
|
||||
* property modifiers), {@jvms 4.5} (field access and property flags),
|
||||
* {@jvms 4.6} (method access and property flags), {@jvms 4.7.6}
|
||||
* (nested class access and property flags), {@jvms 4.7.24} (method
|
||||
* parameters), and {@jvms 4.7.25} (module flags and requires,
|
||||
* exports, and opens flags).
|
||||
*
|
||||
* <p>The {@linkplain #mask() mask} values for the different access
|
||||
* flags are <em>not</em> distinct. Flags are defined for different
|
||||
* kinds of JVM structures and the same bit position has different
|
||||
* meanings in different contexts. For example, {@code 0x0000_0040}
|
||||
* indicates a {@link #VOLATILE volatile} field but a {@linkplain
|
||||
* #BRIDGE bridge method}; {@code 0x0000_0080} indicates a {@link
|
||||
* #TRANSIENT transient} field but a {@linkplain #VARARGS variable
|
||||
* arity (varargs)} method.
|
||||
*
|
||||
* @implSpec
|
||||
* The access flag constants are ordered by non-decreasing mask
|
||||
* value; that is the mask value of a constant is greater than or
|
||||
* equal to the mask value of an immediate neighbor to its (syntactic)
|
||||
* left. If new constants are added, this property will be
|
||||
* maintained. That implies new constants will not necessarily be
|
||||
* added at the end of the existing list.
|
||||
*
|
||||
* @apiNote
|
||||
* The JVM class file format has a new version defined for each new
|
||||
* {@linkplain Runtime.Version#feature() feature release}. A new class
|
||||
* file version may define new access flags or retire old ones. {@code
|
||||
* AccessFlag} is intended to model the set of access flags across
|
||||
* class file format versions. The range of versions an access flag is
|
||||
* recognized is not explicitly indicated in this API. See the current
|
||||
* <cite>The Java Virtual Machine Specification</cite> for
|
||||
* details. Unless otherwise indicated, access flags can be assumed to
|
||||
* be recognized in the {@linkplain Runtime#version() current
|
||||
* version}.
|
||||
*
|
||||
* @see java.lang.reflect.Modifier
|
||||
* @see java.lang.module.ModuleDescriptor.Modifier
|
||||
* @see java.lang.module.ModuleDescriptor.Requires.Modifier
|
||||
* @see java.lang.module.ModuleDescriptor.Exports.Modifier
|
||||
* @see java.lang.module.ModuleDescriptor.Opens.Modifier
|
||||
* @see java.compiler/javax.lang.model.element.Modifier
|
||||
* @since 20
|
||||
*/
|
||||
@SuppressWarnings("doclint:reference") // cross-module link
|
||||
public enum AccessFlag {
|
||||
/**
|
||||
* The access flag {@code ACC_PUBLIC}, corresponding to the source
|
||||
* modifier {@link Modifier#PUBLIC public} with a mask value of
|
||||
* <code>{@value "0x%04x" Modifier#PUBLIC}</code>.
|
||||
*/
|
||||
PUBLIC(Modifier.PUBLIC, true,
|
||||
Set.of(Location.CLASS, Location.FIELD, Location.METHOD,
|
||||
Location.INNER_CLASS)),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_PRIVATE}, corresponding to the
|
||||
* source modifier {@link Modifier#PRIVATE private} with a mask
|
||||
* value of <code>{@value "0x%04x" Modifier#PRIVATE}</code>.
|
||||
*/
|
||||
PRIVATE(Modifier.PRIVATE, true, Location.SET_FIELD_METHOD_INNER_CLASS),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_PROTECTED}, corresponding to the
|
||||
* source modifier {@link Modifier#PROTECTED protected} with a mask
|
||||
* value of <code>{@value "0x%04x" Modifier#PROTECTED}</code>.
|
||||
*/
|
||||
PROTECTED(Modifier.PROTECTED, true, Location.SET_FIELD_METHOD_INNER_CLASS),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_STATIC}, corresponding to the source
|
||||
* modifier {@link Modifier#STATIC static} with a mask value of
|
||||
* <code>{@value "0x%04x" Modifier#STATIC}</code>.
|
||||
*/
|
||||
STATIC(Modifier.STATIC, true, Location.SET_FIELD_METHOD_INNER_CLASS),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_FINAL}, corresponding to the source
|
||||
* modifier {@link Modifier#FINAL final} with a mask
|
||||
* value of <code>{@value "0x%04x" Modifier#FINAL}</code>.
|
||||
*/
|
||||
FINAL(Modifier.FINAL, true,
|
||||
Set.of(Location.CLASS, Location.FIELD, Location.METHOD,
|
||||
Location.INNER_CLASS, Location.METHOD_PARAMETER)),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_SUPER} with a mask value of {@code
|
||||
* 0x0020}.
|
||||
*
|
||||
* @apiNote
|
||||
* In Java SE 8 and above, the JVM treats the {@code ACC_SUPER}
|
||||
* flag as set in every class file (JVMS {@jvms 4.1}).
|
||||
*/
|
||||
SUPER(0x0000_0020, false, Location.SET_CLASS),
|
||||
|
||||
/**
|
||||
* The module flag {@code ACC_OPEN} with a mask value of {@code
|
||||
* 0x0020}.
|
||||
* @see java.lang.module.ModuleDescriptor#isOpen
|
||||
*/
|
||||
OPEN(0x0000_0020, false, Set.of(Location.MODULE)),
|
||||
|
||||
/**
|
||||
* The module requires flag {@code ACC_TRANSITIVE} with a mask
|
||||
* value of {@code 0x0020}.
|
||||
* @see java.lang.module.ModuleDescriptor.Requires.Modifier#TRANSITIVE
|
||||
*/
|
||||
TRANSITIVE(0x0000_0020, false, Location.SET_MODULE_REQUIRES),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_SYNCHRONIZED}, corresponding to the
|
||||
* source modifier {@link Modifier#SYNCHRONIZED synchronized} with
|
||||
* a mask value of <code>{@value "0x%04x" Modifier#SYNCHRONIZED}</code>.
|
||||
*/
|
||||
SYNCHRONIZED(Modifier.SYNCHRONIZED, true, Location.SET_METHOD),
|
||||
|
||||
/**
|
||||
* The module requires flag {@code ACC_STATIC_PHASE} with a mask
|
||||
* value of {@code 0x0040}.
|
||||
* @see java.lang.module.ModuleDescriptor.Requires.Modifier#STATIC
|
||||
*/
|
||||
STATIC_PHASE(0x0000_0040, false, Location.SET_MODULE_REQUIRES),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_VOLATILE}, corresponding to the
|
||||
* source modifier {@link Modifier#VOLATILE volatile} with a mask
|
||||
* value of <code>{@value "0x%04x" Modifier#VOLATILE}</code>.
|
||||
*/
|
||||
VOLATILE(Modifier.VOLATILE, true, Location.SET_FIELD),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_BRIDGE} with a mask value of
|
||||
* <code>{@value "0x%04x" Modifier#BRIDGE}</code>
|
||||
* @see Method#isBridge()
|
||||
*/
|
||||
BRIDGE(Modifier.BRIDGE, false, Location.SET_METHOD),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_TRANSIENT}, corresponding to the
|
||||
* source modifier {@link Modifier#TRANSIENT transient} with a
|
||||
* mask value of <code>{@value "0x%04x" Modifier#TRANSIENT}</code>.
|
||||
*/
|
||||
TRANSIENT(Modifier.TRANSIENT, true, Location.SET_FIELD),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_VARARGS} with a mask value of
|
||||
<code>{@value "0x%04x" Modifier#VARARGS}</code>.
|
||||
* @see Executable#isVarArgs()
|
||||
*/
|
||||
VARARGS(Modifier.VARARGS, false, Location.SET_METHOD),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_NATIVE}, corresponding to the source
|
||||
* modifier {@link Modifier#NATIVE native} with a mask value of
|
||||
* <code>{@value "0x%04x" Modifier#NATIVE}</code>.
|
||||
*/
|
||||
NATIVE(Modifier.NATIVE, true, Location.SET_METHOD),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_INTERFACE} with a mask value of
|
||||
* {@code 0x0200}.
|
||||
* @see Class#isInterface()
|
||||
*/
|
||||
INTERFACE(Modifier.INTERFACE, false, Location.SET_CLASS_INNER_CLASS),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_ABSTRACT}, corresponding to the
|
||||
* source modifier {@link Modifier#ABSTRACT abstract} with a mask
|
||||
* value of <code>{@value "0x%04x" Modifier#ABSTRACT}</code>.
|
||||
*/
|
||||
ABSTRACT(Modifier.ABSTRACT, true,
|
||||
Set.of(Location.CLASS, Location.METHOD, Location.INNER_CLASS)),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_STRICT}, corresponding to the source
|
||||
* modifier {@link Modifier#STRICT strictfp} with a mask value of
|
||||
* <code>{@value "0x%04x" Modifier#STRICT}</code>.
|
||||
*
|
||||
* @apiNote
|
||||
* The {@code ACC_STRICT} access flag is defined for class file
|
||||
* major versions 46 through 60, inclusive (JVMS {@jvms 4.6}),
|
||||
* corresponding to Java SE 1.2 through 16.
|
||||
*/
|
||||
STRICT(Modifier.STRICT, true, Location.SET_METHOD),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_SYNTHETIC} with a mask value of
|
||||
* <code>{@value "0x%04x" Modifier#SYNTHETIC}</code>.
|
||||
* @see Class#isSynthetic()
|
||||
* @see Executable#isSynthetic()
|
||||
* @see java.lang.module.ModuleDescriptor.Modifier#SYNTHETIC
|
||||
*/
|
||||
SYNTHETIC(Modifier.SYNTHETIC, false,
|
||||
Set.of(Location.CLASS, Location.FIELD, Location.METHOD,
|
||||
Location.INNER_CLASS, Location.METHOD_PARAMETER,
|
||||
Location.MODULE, Location.MODULE_REQUIRES,
|
||||
Location.MODULE_EXPORTS, Location.MODULE_OPENS)),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_ANNOTATION} with a mask value of
|
||||
* <code>{@value "0x%04x" Modifier#ANNOTATION}</code>.
|
||||
* @see Class#isAnnotation()
|
||||
*/
|
||||
ANNOTATION(Modifier.ANNOTATION, false, Location.SET_CLASS_INNER_CLASS),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_ENUM} with a mask value of
|
||||
* <code>{@value "0x%04x" Modifier#ENUM}</code>.
|
||||
* @see Class#isEnum()
|
||||
*/
|
||||
ENUM(Modifier.ENUM, false,
|
||||
Set.of(Location.CLASS, Location.FIELD, Location.INNER_CLASS)),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_MANDATED} with a mask value of
|
||||
* <code>{@value "0x%04x" Modifier#MANDATED}</code>.
|
||||
*/
|
||||
MANDATED(Modifier.MANDATED, false,
|
||||
Set.of(Location.METHOD_PARAMETER,
|
||||
Location.MODULE, Location.MODULE_REQUIRES,
|
||||
Location.MODULE_EXPORTS, Location.MODULE_OPENS)),
|
||||
|
||||
/**
|
||||
* The access flag {@code ACC_MODULE} with a mask value of {@code
|
||||
* 0x8000}.
|
||||
*/
|
||||
MODULE(0x0000_8000, false, Location.SET_CLASS)
|
||||
;
|
||||
|
||||
// May want to override toString for a different enum constant ->
|
||||
// name mapping.
|
||||
|
||||
private final int mask;
|
||||
private final boolean sourceModifier;
|
||||
|
||||
// Intentionally using Set rather than EnumSet since EnumSet is
|
||||
// mutable.
|
||||
private final Set<Location> locations;
|
||||
|
||||
private AccessFlag(int mask, boolean sourceModifier, Set<Location> locations) {
|
||||
this.mask = mask;
|
||||
this.sourceModifier = sourceModifier;
|
||||
this.locations = locations;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the corresponding integer mask for the access flag}
|
||||
*/
|
||||
public int mask() {
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return whether or not the flag has a directly corresponding
|
||||
* modifier in the Java programming language}
|
||||
*/
|
||||
public boolean sourceModifier() {
|
||||
return sourceModifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return kinds of constructs the flag can be applied to}
|
||||
*/
|
||||
public Set<Location> locations() {
|
||||
return locations;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return an unmodifiable set of access flags for the given mask value
|
||||
* appropriate for the location in question}
|
||||
*
|
||||
* @param mask bit mask of access flags
|
||||
* @param location context to interpret mask value
|
||||
* @throws IllegalArgumentException if the mask contains bit
|
||||
* positions not support for the location in question
|
||||
*/
|
||||
public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) {
|
||||
Set<AccessFlag> result = java.util.EnumSet.noneOf(AccessFlag.class);
|
||||
for (var accessFlag : LocationToFlags.locationToFlags.get(location)) {
|
||||
int accessMask = accessFlag.mask();
|
||||
if ((mask & accessMask) != 0) {
|
||||
result.add(accessFlag);
|
||||
mask = mask & ~accessMask;
|
||||
}
|
||||
}
|
||||
if (mask != 0) {
|
||||
throw new IllegalArgumentException("Unmatched bit position 0x" +
|
||||
Integer.toHexString(mask) +
|
||||
" for location " + location);
|
||||
}
|
||||
return Collections.unmodifiableSet(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* A location within a class file where flags can be applied.
|
||||
*
|
||||
* Note that since these locations represent class file structures
|
||||
* rather than language structures many language structures, such
|
||||
* as constructors and interfaces, are <em>not</em> present.
|
||||
* @since 20
|
||||
*/
|
||||
public enum Location {
|
||||
/**
|
||||
* Class location.
|
||||
* @jvms 4.1 The ClassFile Structure
|
||||
*/
|
||||
CLASS,
|
||||
|
||||
/**
|
||||
* Field location.
|
||||
* @jvms 4.5 Fields
|
||||
*/
|
||||
FIELD,
|
||||
|
||||
/**
|
||||
* Method location.
|
||||
* @jvms 4.6 Method
|
||||
*/
|
||||
METHOD,
|
||||
|
||||
/**
|
||||
* Inner class location.
|
||||
* @jvms 4.7.6 The InnerClasses Attribute
|
||||
*/
|
||||
INNER_CLASS,
|
||||
|
||||
/**
|
||||
* Method parameter loccation.
|
||||
* @jvms 4.7.24. The MethodParameters Attribute
|
||||
*/
|
||||
METHOD_PARAMETER,
|
||||
|
||||
/**
|
||||
* Module location
|
||||
* @jvms 4.7.25. The Module Attribute
|
||||
*/
|
||||
MODULE,
|
||||
|
||||
/**
|
||||
* Module requires location
|
||||
* @jvms 4.7.25. The Module Attribute
|
||||
*/
|
||||
MODULE_REQUIRES,
|
||||
|
||||
/**
|
||||
* Module exports location
|
||||
* @jvms 4.7.25. The Module Attribute
|
||||
*/
|
||||
MODULE_EXPORTS,
|
||||
|
||||
/**
|
||||
* Module opens location
|
||||
* @jvms 4.7.25. The Module Attribute
|
||||
*/
|
||||
MODULE_OPENS;
|
||||
|
||||
// Repeated sets of locations used by AccessFlag constants
|
||||
private static final Set<Location> SET_FIELD_METHOD_INNER_CLASS =
|
||||
Set.of(FIELD, METHOD, INNER_CLASS);
|
||||
private static final Set<Location> SET_METHOD = Set.of(METHOD);
|
||||
private static final Set<Location> SET_FIELD = Set.of(FIELD);
|
||||
private static final Set<Location> SET_CLASS = Set.of(CLASS);
|
||||
private static final Set<Location> SET_CLASS_INNER_CLASS =
|
||||
Set.of(CLASS, INNER_CLASS);
|
||||
private static final Set<Location> SET_MODULE_REQUIRES =
|
||||
Set.of(MODULE_REQUIRES);
|
||||
}
|
||||
|
||||
private static class LocationToFlags {
|
||||
private static Map<Location, Set<AccessFlag>> locationToFlags =
|
||||
Map.ofEntries(entry(Location.CLASS,
|
||||
Set.of(PUBLIC, FINAL, SUPER,
|
||||
INTERFACE, ABSTRACT,
|
||||
SYNTHETIC, ANNOTATION,
|
||||
ENUM, AccessFlag.MODULE)),
|
||||
entry(Location.FIELD,
|
||||
Set.of(PUBLIC, PRIVATE, PROTECTED,
|
||||
STATIC, FINAL, VOLATILE,
|
||||
TRANSIENT, SYNTHETIC, ENUM)),
|
||||
entry(Location.METHOD,
|
||||
Set.of(PUBLIC, PRIVATE, PROTECTED,
|
||||
STATIC, FINAL, SYNCHRONIZED,
|
||||
BRIDGE, VARARGS, NATIVE,
|
||||
ABSTRACT, STRICT, SYNTHETIC)),
|
||||
entry(Location.INNER_CLASS,
|
||||
Set.of(PUBLIC, PRIVATE, PROTECTED,
|
||||
STATIC, FINAL, INTERFACE, ABSTRACT,
|
||||
SYNTHETIC, ANNOTATION, ENUM)),
|
||||
entry(Location.METHOD_PARAMETER,
|
||||
Set.of(FINAL, SYNTHETIC, MANDATED)),
|
||||
entry(Location.MODULE,
|
||||
Set.of(OPEN, SYNTHETIC, MANDATED)),
|
||||
entry(Location.MODULE_REQUIRES,
|
||||
Set.of(TRANSITIVE, STATIC_PHASE, SYNTHETIC, MANDATED)),
|
||||
entry(Location.MODULE_EXPORTS,
|
||||
Set.of(SYNTHETIC, MANDATED)),
|
||||
entry(Location.MODULE_OPENS,
|
||||
Set.of(SYNTHETIC, MANDATED)));
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ package java.lang.reflect;
|
|||
import java.lang.annotation.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Stream;
|
||||
|
@ -204,9 +205,25 @@ public abstract sealed class Executable extends AccessibleObject
|
|||
/**
|
||||
* {@return the Java language {@linkplain Modifier modifiers} for
|
||||
* the executable represented by this object}
|
||||
* @see #accessFlags
|
||||
*/
|
||||
public abstract int getModifiers();
|
||||
|
||||
/**
|
||||
* {@return an unmodifiable set of the {@linkplain AccessFlag
|
||||
* access flags} for the executable represented by this object,
|
||||
* possibly empty}
|
||||
*
|
||||
* @see #getModifiers()
|
||||
* @jvms 4.6 Methods
|
||||
* @since 20
|
||||
*/
|
||||
@Override
|
||||
public Set<AccessFlag> accessFlags() {
|
||||
return AccessFlag.maskToAccessFlags(getModifiers(),
|
||||
AccessFlag.Location.METHOD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of {@code TypeVariable} objects that represent the
|
||||
* type variables declared by the generic declaration represented by this
|
||||
|
|
|
@ -37,6 +37,7 @@ import sun.reflect.generics.factory.GenericsFactory;
|
|||
import sun.reflect.generics.scope.ClassScope;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Objects;
|
||||
import sun.reflect.annotation.AnnotationParser;
|
||||
import sun.reflect.annotation.AnnotationSupport;
|
||||
|
@ -202,6 +203,7 @@ class Field extends AccessibleObject implements Member {
|
|||
* be used to decode the modifiers.
|
||||
*
|
||||
* @see Modifier
|
||||
* @see #accessFlags()
|
||||
* @jls 8.3 Field Declarations
|
||||
* @jls 9.3 Field (Constant) Declarations
|
||||
*/
|
||||
|
@ -209,6 +211,18 @@ class Field extends AccessibleObject implements Member {
|
|||
return modifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return an unmodifiable set of the {@linkplain AccessFlag
|
||||
* access flags} for this field, possibly empty}
|
||||
* @see #getModifiers()
|
||||
* @jvms 4.5 Fields
|
||||
* @since 20
|
||||
*/
|
||||
@Override
|
||||
public Set<AccessFlag> accessFlags() {
|
||||
return AccessFlag.maskToAccessFlags(getModifiers(), AccessFlag.Location.FIELD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this field represents an element of
|
||||
* an enumerated class; returns {@code false} otherwise.
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
package java.lang.reflect;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Member is an interface that reflects identifying information about
|
||||
* a single member (a field or a method) or a constructor.
|
||||
|
@ -76,9 +78,25 @@ public interface Member {
|
|||
*
|
||||
* @return the Java language modifiers for the underlying member
|
||||
* @see Modifier
|
||||
* @see #accessFlags()
|
||||
*/
|
||||
public int getModifiers();
|
||||
|
||||
|
||||
/**
|
||||
* {@return an unmodifiable set of the {@linkplain AccessFlag
|
||||
* access flags} for this member, possibly empty}
|
||||
*
|
||||
* @implSpec
|
||||
* The default implementation throws {@link
|
||||
* UnsupportedOperationException}.
|
||||
* @see #getModifiers()
|
||||
* @since 20
|
||||
*/
|
||||
public default Set<AccessFlag> accessFlags() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this member was introduced by
|
||||
* the compiler; returns {@code false} otherwise.
|
||||
|
|
|
@ -254,72 +254,84 @@ public class Modifier {
|
|||
/**
|
||||
* The {@code int} value representing the {@code public}
|
||||
* modifier.
|
||||
* @see AccessFlag#PUBLIC
|
||||
*/
|
||||
public static final int PUBLIC = 0x00000001;
|
||||
|
||||
/**
|
||||
* The {@code int} value representing the {@code private}
|
||||
* modifier.
|
||||
* @see AccessFlag#PRIVATE
|
||||
*/
|
||||
public static final int PRIVATE = 0x00000002;
|
||||
|
||||
/**
|
||||
* The {@code int} value representing the {@code protected}
|
||||
* modifier.
|
||||
* @see AccessFlag#PROTECTED
|
||||
*/
|
||||
public static final int PROTECTED = 0x00000004;
|
||||
|
||||
/**
|
||||
* The {@code int} value representing the {@code static}
|
||||
* modifier.
|
||||
* @see AccessFlag#STATIC
|
||||
*/
|
||||
public static final int STATIC = 0x00000008;
|
||||
|
||||
/**
|
||||
* The {@code int} value representing the {@code final}
|
||||
* modifier.
|
||||
* @see AccessFlag#FINAL
|
||||
*/
|
||||
public static final int FINAL = 0x00000010;
|
||||
|
||||
/**
|
||||
* The {@code int} value representing the {@code synchronized}
|
||||
* modifier.
|
||||
* @see AccessFlag#SYNCHRONIZED
|
||||
*/
|
||||
public static final int SYNCHRONIZED = 0x00000020;
|
||||
|
||||
/**
|
||||
* The {@code int} value representing the {@code volatile}
|
||||
* modifier.
|
||||
* @see AccessFlag#VOLATILE
|
||||
*/
|
||||
public static final int VOLATILE = 0x00000040;
|
||||
|
||||
/**
|
||||
* The {@code int} value representing the {@code transient}
|
||||
* modifier.
|
||||
* @see AccessFlag#TRANSIENT
|
||||
*/
|
||||
public static final int TRANSIENT = 0x00000080;
|
||||
|
||||
/**
|
||||
* The {@code int} value representing the {@code native}
|
||||
* modifier.
|
||||
* @see AccessFlag#NATIVE
|
||||
*/
|
||||
public static final int NATIVE = 0x00000100;
|
||||
|
||||
/**
|
||||
* The {@code int} value representing the {@code interface}
|
||||
* modifier.
|
||||
* @see AccessFlag#INTERFACE
|
||||
*/
|
||||
public static final int INTERFACE = 0x00000200;
|
||||
|
||||
/**
|
||||
* The {@code int} value representing the {@code abstract}
|
||||
* modifier.
|
||||
* @see AccessFlag#ABSTRACT
|
||||
*/
|
||||
public static final int ABSTRACT = 0x00000400;
|
||||
|
||||
/**
|
||||
* The {@code int} value representing the {@code strictfp}
|
||||
* modifier.
|
||||
* @see AccessFlag#STRICT
|
||||
*/
|
||||
public static final int STRICT = 0x00000800;
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ package java.lang.reflect;
|
|||
import java.lang.annotation.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Objects;
|
||||
import sun.reflect.annotation.AnnotationSupport;
|
||||
|
||||
|
@ -161,6 +162,20 @@ public final class Parameter implements AnnotatedElement {
|
|||
return modifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return an unmodifiable set of the {@linkplain AccessFlag
|
||||
* access flags} for the parameter represented by this object,
|
||||
* possibly empty}
|
||||
*
|
||||
* @see #getModifiers()
|
||||
* @jvms 4.7.24 The MethodParameters Attribute
|
||||
* @since 20
|
||||
*/
|
||||
public Set<AccessFlag> accessFlags() {
|
||||
return AccessFlag.maskToAccessFlags(getModifiers(),
|
||||
AccessFlag.Location.METHOD_PARAMETER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the parameter. If the parameter's name is
|
||||
* {@linkplain #isNamePresent() present}, then this method returns
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue