mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-14 18:03:44 +00:00
8364187: Make getClassAccessFlagsRaw non-native
Reviewed-by: thartmann, rriggs, liach
This commit is contained in:
parent
2ba8a06f0c
commit
ee3665bca0
@ -870,6 +870,7 @@ int java_lang_Class::_classRedefinedCount_offset;
|
||||
int java_lang_Class::_reflectionData_offset;
|
||||
int java_lang_Class::_modifiers_offset;
|
||||
int java_lang_Class::_is_primitive_offset;
|
||||
int java_lang_Class::_raw_access_flags_offset;
|
||||
|
||||
bool java_lang_Class::_offsets_computed = false;
|
||||
GrowableArray<Klass*>* java_lang_Class::_fixup_mirror_list = nullptr;
|
||||
@ -1073,6 +1074,10 @@ void java_lang_Class::allocate_mirror(Klass* k, bool is_scratch, Handle protecti
|
||||
// Set the modifiers flag.
|
||||
u2 computed_modifiers = k->compute_modifier_flags();
|
||||
set_modifiers(mirror(), computed_modifiers);
|
||||
// Set the raw access_flags, this is used by reflection instead of modifier flags.
|
||||
// The Java code for array classes gets the access flags from the element type.
|
||||
assert(!k->is_array_klass() || k->access_flags().as_unsigned_short() == 0, "access flags are not set for arrays");
|
||||
set_raw_access_flags(mirror(), k->access_flags().as_unsigned_short());
|
||||
|
||||
InstanceMirrorKlass* mk = InstanceMirrorKlass::cast(mirror->klass());
|
||||
assert(oop_size(mirror()) == mk->instance_size(k), "should have been set");
|
||||
@ -1378,6 +1383,8 @@ oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, Basic
|
||||
assert(static_oop_field_count(java_class) == 0, "should have been zeroed by allocation");
|
||||
#endif
|
||||
set_modifiers(java_class, JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC);
|
||||
set_raw_access_flags(java_class, JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC);
|
||||
|
||||
set_is_primitive(java_class);
|
||||
return java_class;
|
||||
}
|
||||
@ -1519,6 +1526,7 @@ oop java_lang_Class::primitive_mirror(BasicType t) {
|
||||
macro(_reflectionData_offset, k, "reflectionData", java_lang_ref_SoftReference_signature, false); \
|
||||
macro(_signers_offset, k, "signers", object_array_signature, false); \
|
||||
macro(_modifiers_offset, k, vmSymbols::modifiers_name(), char_signature, false); \
|
||||
macro(_raw_access_flags_offset, k, "classFileAccessFlags", char_signature, false); \
|
||||
macro(_protection_domain_offset, k, "protectionDomain", java_security_ProtectionDomain_signature, false); \
|
||||
macro(_is_primitive_offset, k, "primitive", bool_signature, false);
|
||||
|
||||
@ -1564,6 +1572,16 @@ void java_lang_Class::set_modifiers(oop the_class_mirror, u2 value) {
|
||||
the_class_mirror->char_field_put(_modifiers_offset, value);
|
||||
}
|
||||
|
||||
int java_lang_Class::raw_access_flags(oop the_class_mirror) {
|
||||
assert(_raw_access_flags_offset != 0, "offsets should have been initialized");
|
||||
return the_class_mirror->char_field(_raw_access_flags_offset);
|
||||
}
|
||||
|
||||
void java_lang_Class::set_raw_access_flags(oop the_class_mirror, u2 value) {
|
||||
assert(_raw_access_flags_offset != 0, "offsets should have been initialized");
|
||||
the_class_mirror->char_field_put(_raw_access_flags_offset, value);
|
||||
}
|
||||
|
||||
|
||||
// Note: JDK1.1 and before had a privateInfo_offset field which was used for the
|
||||
// platform thread structure, and a eetop offset which was used for thread
|
||||
|
||||
@ -258,6 +258,7 @@ class java_lang_Class : AllStatic {
|
||||
static int _reflectionData_offset;
|
||||
static int _modifiers_offset;
|
||||
static int _is_primitive_offset;
|
||||
static int _raw_access_flags_offset;
|
||||
|
||||
static bool _offsets_computed;
|
||||
|
||||
@ -342,6 +343,9 @@ class java_lang_Class : AllStatic {
|
||||
static int modifiers(oop java_class);
|
||||
static void set_modifiers(oop java_class, u2 value);
|
||||
|
||||
static int raw_access_flags(oop java_class);
|
||||
static void set_raw_access_flags(oop java_class, u2 value);
|
||||
|
||||
static size_t oop_size(oop java_class);
|
||||
static void set_oop_size(HeapWord* java_class, size_t size);
|
||||
static int static_oop_field_count(oop java_class);
|
||||
|
||||
@ -314,8 +314,6 @@ class methodHandle;
|
||||
do_intrinsic(_Class_cast, java_lang_Class, Class_cast_name, object_object_signature, F_R) \
|
||||
do_name( Class_cast_name, "cast") \
|
||||
\
|
||||
do_intrinsic(_getClassAccessFlags, reflect_Reflection, getClassAccessFlags_name, class_int_signature, F_SN) \
|
||||
do_name( getClassAccessFlags_name, "getClassAccessFlags") \
|
||||
do_intrinsic(_getLength, java_lang_reflect_Array, getLength_name, object_int_signature, F_SN) \
|
||||
do_name( getLength_name, "getLength") \
|
||||
\
|
||||
|
||||
@ -760,7 +760,6 @@ bool C2Compiler::is_intrinsic_supported(vmIntrinsics::ID id) {
|
||||
case vmIntrinsics::_isInstance:
|
||||
case vmIntrinsics::_isHidden:
|
||||
case vmIntrinsics::_getSuperclass:
|
||||
case vmIntrinsics::_getClassAccessFlags:
|
||||
case vmIntrinsics::_floatToRawIntBits:
|
||||
case vmIntrinsics::_floatToIntBits:
|
||||
case vmIntrinsics::_intBitsToFloat:
|
||||
|
||||
@ -519,8 +519,7 @@ bool LibraryCallKit::try_to_inline(int predicate) {
|
||||
|
||||
case vmIntrinsics::_isInstance:
|
||||
case vmIntrinsics::_isHidden:
|
||||
case vmIntrinsics::_getSuperclass:
|
||||
case vmIntrinsics::_getClassAccessFlags: return inline_native_Class_query(intrinsic_id());
|
||||
case vmIntrinsics::_getSuperclass: return inline_native_Class_query(intrinsic_id());
|
||||
|
||||
case vmIntrinsics::_floatToRawIntBits:
|
||||
case vmIntrinsics::_floatToIntBits:
|
||||
@ -4007,10 +4006,6 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) {
|
||||
prim_return_value = null();
|
||||
return_type = TypeInstPtr::MIRROR->cast_to_ptr_type(TypePtr::BotPTR);
|
||||
break;
|
||||
case vmIntrinsics::_getClassAccessFlags:
|
||||
prim_return_value = intcon(JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC);
|
||||
return_type = TypeInt::CHAR;
|
||||
break;
|
||||
default:
|
||||
fatal_unexpected_iid(id);
|
||||
break;
|
||||
@ -4106,11 +4101,6 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) {
|
||||
}
|
||||
break;
|
||||
|
||||
case vmIntrinsics::_getClassAccessFlags:
|
||||
p = basic_plus_adr(kls, in_bytes(Klass::access_flags_offset()));
|
||||
query_value = make_load(nullptr, p, TypeInt::CHAR, T_CHAR, MemNode::unordered);
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal_unexpected_iid(id);
|
||||
break;
|
||||
|
||||
@ -1981,13 +1981,11 @@ LoadNode::load_array_final_field(const TypeKlassPtr *tkls,
|
||||
"must not happen");
|
||||
if (tkls->offset() == in_bytes(Klass::access_flags_offset())) {
|
||||
// The field is Klass::_access_flags. Return its (constant) value.
|
||||
// (Folds up the 2nd indirection in Reflection.getClassAccessFlags(aClassConstant).)
|
||||
assert(Opcode() == Op_LoadUS, "must load an unsigned short from _access_flags");
|
||||
return TypeInt::make(klass->access_flags());
|
||||
}
|
||||
if (tkls->offset() == in_bytes(Klass::misc_flags_offset())) {
|
||||
// The field is Klass::_misc_flags. Return its (constant) value.
|
||||
// (Folds up the 2nd indirection in Reflection.getClassAccessFlags(aClassConstant).)
|
||||
assert(Opcode() == Op_LoadUB, "must load an unsigned byte from _misc_flags");
|
||||
return TypeInt::make(klass->misc_flags());
|
||||
}
|
||||
|
||||
@ -1741,19 +1741,6 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofC
|
||||
}
|
||||
JVM_END
|
||||
|
||||
JVM_ENTRY(jint, JVM_GetClassAccessFlags(JNIEnv *env, jclass cls))
|
||||
{
|
||||
oop mirror = JNIHandles::resolve_non_null(cls);
|
||||
if (java_lang_Class::is_primitive(mirror)) {
|
||||
// Primitive type
|
||||
return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC;
|
||||
}
|
||||
|
||||
Klass* k = java_lang_Class::as_Klass(mirror);
|
||||
return k->access_flags().as_class_flags();
|
||||
}
|
||||
JVM_END
|
||||
|
||||
JVM_ENTRY(jboolean, JVM_AreNestMates(JNIEnv *env, jclass current, jclass member))
|
||||
{
|
||||
Klass* c = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(current));
|
||||
|
||||
@ -240,7 +240,7 @@ public final class Class<T> implements java.io.Serializable,
|
||||
* This constructor is not used and prevents the default constructor being
|
||||
* generated.
|
||||
*/
|
||||
private Class(ClassLoader loader, Class<?> arrayComponentType, char mods, ProtectionDomain pd, boolean isPrim) {
|
||||
private Class(ClassLoader loader, Class<?> arrayComponentType, char mods, ProtectionDomain pd, boolean isPrim, char flags) {
|
||||
// Initialize final field for classLoader. The initialization value of non-null
|
||||
// prevents future JIT optimizations from assuming this final field is null.
|
||||
// The following assignments are done directly by the VM without calling this constructor.
|
||||
@ -249,6 +249,7 @@ public final class Class<T> implements java.io.Serializable,
|
||||
modifiers = mods;
|
||||
protectionDomain = pd;
|
||||
primitive = isPrim;
|
||||
classFileAccessFlags = flags;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1012,6 +1013,7 @@ public final class Class<T> implements java.io.Serializable,
|
||||
private transient Object classData; // Set by VM
|
||||
private transient Object[] signers; // Read by VM, mutable
|
||||
private final transient char modifiers; // Set by the VM
|
||||
private final transient char classFileAccessFlags; // Set by the VM
|
||||
private final transient boolean primitive; // Set by the VM if the Class is a primitive type.
|
||||
|
||||
// package-private
|
||||
@ -1383,13 +1385,13 @@ public final class Class<T> implements java.io.Serializable,
|
||||
// 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.
|
||||
// Use getClassAccessFlagsRaw to expose SUPER status.
|
||||
// Use getClassFileAccessFlags to expose SUPER status.
|
||||
var location = (isMemberClass() || isLocalClass() ||
|
||||
isAnonymousClass() || isArray()) ?
|
||||
AccessFlag.Location.INNER_CLASS :
|
||||
AccessFlag.Location.CLASS;
|
||||
return getReflectionFactory().parseAccessFlags((location == AccessFlag.Location.CLASS) ?
|
||||
getClassAccessFlagsRaw() : getModifiers(), location, this);
|
||||
getClassFileAccessFlags() : getModifiers(), location, this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4134,17 +4136,16 @@ public final class Class<T> implements java.io.Serializable,
|
||||
|
||||
private native int getClassFileVersion0();
|
||||
|
||||
/*
|
||||
* Return the access flags as they were in the class's bytecode, including
|
||||
* the original setting of ACC_SUPER.
|
||||
*
|
||||
* If the class is an array type then the access flags of the element type is
|
||||
* returned. If the class is a primitive then ACC_ABSTRACT | ACC_FINAL | ACC_PUBLIC.
|
||||
*/
|
||||
private int getClassAccessFlagsRaw() {
|
||||
Class<?> c = isArray() ? elementType() : this;
|
||||
return c.getClassAccessFlagsRaw0();
|
||||
}
|
||||
|
||||
private native int getClassAccessFlagsRaw0();
|
||||
/**
|
||||
* Return the access flags as they were in the class's bytecode, including
|
||||
* the original setting of ACC_SUPER.
|
||||
*
|
||||
* If this {@code Class} object represents a primitive type or
|
||||
* void, the flags are {@code PUBLIC}, {@code ABSTRACT}, and
|
||||
* {@code FINAL}.
|
||||
* If this {@code Class} object represents an array type, return 0.
|
||||
*/
|
||||
int getClassFileAccessFlags() {
|
||||
return classFileAccessFlags;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2022,6 +2022,9 @@ public final class System {
|
||||
public byte[] getRawExecutableTypeAnnotations(Executable executable) {
|
||||
return Class.getExecutableTypeAnnotationBytes(executable);
|
||||
}
|
||||
public int getClassFileAccessFlags(Class<?> klass) {
|
||||
return klass.getClassFileAccessFlags();
|
||||
}
|
||||
public <E extends Enum<E>>
|
||||
E[] getEnumConstantsShared(Class<E> klass) {
|
||||
return klass.getEnumConstantsShared();
|
||||
|
||||
@ -112,6 +112,11 @@ public interface JavaLangAccess {
|
||||
*/
|
||||
byte[] getRawExecutableTypeAnnotations(Executable executable);
|
||||
|
||||
/**
|
||||
* Get the int value of the Class's class-file access flags.
|
||||
*/
|
||||
int getClassFileAccessFlags(Class<?> klass);
|
||||
|
||||
/**
|
||||
* Returns the elements of an enum class or null if the
|
||||
* Class object does not represent an enum type;
|
||||
|
||||
@ -81,8 +81,9 @@ public class Reflection {
|
||||
to compatibility reasons; see 4471811. Only the values of the
|
||||
low 13 bits (i.e., a mask of 0x1FFF) are guaranteed to be
|
||||
valid. */
|
||||
@IntrinsicCandidate
|
||||
public static native int getClassAccessFlags(Class<?> c);
|
||||
public static int getClassAccessFlags(Class<?> c) {
|
||||
return SharedSecrets.getJavaLangAccess().getClassFileAccessFlags(c);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -75,7 +75,6 @@ static JNINativeMethod methods[] = {
|
||||
{"isRecord0", "()Z", (void *)&JVM_IsRecord},
|
||||
{"getPermittedSubclasses0", "()[" CLS, (void *)&JVM_GetPermittedSubclasses},
|
||||
{"getClassFileVersion0", "()I", (void *)&JVM_GetClassFileVersion},
|
||||
{"getClassAccessFlagsRaw0", "()I", (void *)&JVM_GetClassAccessFlags},
|
||||
};
|
||||
|
||||
#undef OBJ
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2025, 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
|
||||
@ -33,12 +33,6 @@ Java_jdk_internal_reflect_Reflection_getCallerClass(JNIEnv *env, jclass unused)
|
||||
return JVM_GetCallerClass(env);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_jdk_internal_reflect_Reflection_getClassAccessFlags(JNIEnv *env, jclass unused, jclass cls)
|
||||
{
|
||||
return JVM_GetClassAccessFlags(env, cls);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_jdk_internal_reflect_Reflection_areNestMates(JNIEnv *env, jclass unused, jclass current, jclass member)
|
||||
{
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@ -32,6 +32,7 @@
|
||||
*/
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Set;
|
||||
|
||||
public class ClassAccessFlagsRawTest {
|
||||
|
||||
@ -48,28 +49,53 @@ public class ClassAccessFlagsRawTest {
|
||||
|
||||
public static void main(String argv[]) throws Throwable {
|
||||
Class<?> cl = java.lang.Class.class;
|
||||
m = cl.getDeclaredMethod("getClassAccessFlagsRaw", new Class[0]);
|
||||
m = cl.getDeclaredMethod("getClassFileAccessFlags", new Class[0]);
|
||||
m.setAccessible(true);
|
||||
|
||||
testIt("SUPERset", 0x21); // ACC_SUPER 0x20 + ACC_PUBLIC 0x1
|
||||
testIt("SUPERnotset", Modifier.PUBLIC);
|
||||
|
||||
// test primitive array. should return ACC_ABSTRACT | ACC_FINAL | ACC_PUBLIC.
|
||||
int flags = (int)m.invoke((new int[3]).getClass());
|
||||
// Test that primitive should return ACC_ABSTRACT | ACC_FINAL | ACC_PUBLIC.
|
||||
int[] arr = new int[3];
|
||||
if (!arr.getClass().getComponentType().isPrimitive()) {
|
||||
throw new RuntimeException("not primitive");
|
||||
}
|
||||
int flags = (int)m.invoke(arr.getClass().getComponentType());
|
||||
if (flags != (Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC)) {
|
||||
throw new RuntimeException(
|
||||
"expected 0x411, got 0x" + Integer.toHexString(flags) + " for primitive array");
|
||||
"expected 0x411, got 0x" + Integer.toHexString(flags) + " for primitive type");
|
||||
}
|
||||
|
||||
// test object array. should return flags of component.
|
||||
flags = (int)m.invoke((new SUPERnotset[2]).getClass());
|
||||
if (flags != Modifier.PUBLIC) {
|
||||
// Test that primitive array raw access flags return 0.
|
||||
flags = (int)m.invoke(arr.getClass());
|
||||
if (flags != 0) {
|
||||
throw new RuntimeException(
|
||||
"expected 0x1, got 0x" + Integer.toHexString(flags) + " for object array");
|
||||
"expected 0x0 got 0x" + Integer.toHexString(flags) + " for primitive array");
|
||||
}
|
||||
|
||||
// test multi-dimensional object array. should return flags of component.
|
||||
flags = (int)m.invoke((new SUPERnotset[4][2]).getClass());
|
||||
// Test that the modifier flags return element type flags.
|
||||
flags = (int)arr.getClass().getModifiers();
|
||||
if (flags != (Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC)) {
|
||||
throw new RuntimeException(
|
||||
"expected 0x411, got 0x" + Integer.toHexString(flags) + " for primitive type");
|
||||
}
|
||||
|
||||
// Test that AccessFlags set will return element type access flags.
|
||||
Set<AccessFlag> aacc = arr.getClass().accessFlags();
|
||||
if (!aacc.containsAll(Set.of(AccessFlag.FINAL, AccessFlag.ABSTRACT, AccessFlag.PUBLIC))) {
|
||||
throw new RuntimeException(
|
||||
"AccessFlags should contain FINAL, ABSTRACT and PUBLIC for primitive type");
|
||||
}
|
||||
|
||||
// Test object array. Raw access flags are 0 for arrays.
|
||||
flags = (int)m.invoke((new SUPERnotset[2]).getClass());
|
||||
if (flags != 0) {
|
||||
throw new RuntimeException(
|
||||
"expected 0x0, got 0x" + Integer.toHexString(flags) + " for object array");
|
||||
}
|
||||
|
||||
// Test object array component type.
|
||||
flags = (int)m.invoke((new SUPERnotset[2]).getClass().getComponentType());
|
||||
if (flags != Modifier.PUBLIC) {
|
||||
throw new RuntimeException(
|
||||
"expected 0x1, got 0x" + Integer.toHexString(flags) + " for object array");
|
||||
|
||||
@ -148,7 +148,8 @@ public class ModuleSetAccessibleTest {
|
||||
|
||||
// non-public constructor
|
||||
Constructor<?> ctor
|
||||
= Class.class.getDeclaredConstructor(ClassLoader.class, Class.class, char.class, ProtectionDomain.class, boolean.class);
|
||||
= Class.class.getDeclaredConstructor(ClassLoader.class, Class.class, char.class,
|
||||
ProtectionDomain.class, boolean.class, char.class);
|
||||
AccessibleObject[] ctors = { ctor };
|
||||
|
||||
try {
|
||||
|
||||
@ -194,7 +194,8 @@ public class TrySetAccessibleTest {
|
||||
|
||||
// non-public constructor
|
||||
Constructor<?> ctor
|
||||
= Class.class.getDeclaredConstructor(ClassLoader.class, Class.class, char.class, ProtectionDomain.class, boolean.class);
|
||||
= Class.class.getDeclaredConstructor(ClassLoader.class, Class.class, char.class,
|
||||
ProtectionDomain.class, boolean.class, char.class);
|
||||
AccessibleObject[] ctors = { ctor };
|
||||
|
||||
assertFalse(ctor.trySetAccessible());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user