8257596: Clarify trusted final fields for record classes
Reviewed-by: hseigel, chegar, psandoz
This commit is contained in:
parent
b1afed7501
commit
2001da3dd4
@ -739,6 +739,12 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InstanceKlass::is_record() const {
|
||||||
|
return _record_components != NULL &&
|
||||||
|
is_final() &&
|
||||||
|
java_super() == SystemDictionary::Record_klass();
|
||||||
|
}
|
||||||
|
|
||||||
bool InstanceKlass::is_sealed() const {
|
bool InstanceKlass::is_sealed() const {
|
||||||
return _permitted_subclasses != NULL &&
|
return _permitted_subclasses != NULL &&
|
||||||
_permitted_subclasses != Universe::the_empty_short_array();
|
_permitted_subclasses != Universe::the_empty_short_array();
|
||||||
|
@ -473,7 +473,7 @@ class InstanceKlass: public Klass {
|
|||||||
void set_record_components(Array<RecordComponent*>* record_components) {
|
void set_record_components(Array<RecordComponent*>* record_components) {
|
||||||
_record_components = record_components;
|
_record_components = record_components;
|
||||||
}
|
}
|
||||||
bool is_record() const { return _record_components != NULL; }
|
bool is_record() const;
|
||||||
|
|
||||||
// permitted subclasses
|
// permitted subclasses
|
||||||
Array<u2>* permitted_subclasses() const { return _permitted_subclasses; }
|
Array<u2>* permitted_subclasses() const { return _permitted_subclasses; }
|
||||||
|
@ -1851,6 +1851,9 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass,
|
|||||||
}
|
}
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
|
// A class is a record if and only if it is final and a direct subclass of
|
||||||
|
// java.lang.Record and has a Record attribute; otherwise, it is not a record.
|
||||||
JVM_ENTRY(jboolean, JVM_IsRecord(JNIEnv *env, jclass cls))
|
JVM_ENTRY(jboolean, JVM_IsRecord(JNIEnv *env, jclass cls))
|
||||||
{
|
{
|
||||||
JVMWrapper("JVM_IsRecord");
|
JVMWrapper("JVM_IsRecord");
|
||||||
@ -1864,6 +1867,11 @@ JVM_ENTRY(jboolean, JVM_IsRecord(JNIEnv *env, jclass cls))
|
|||||||
}
|
}
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
// Returns an array containing the components of the Record attribute,
|
||||||
|
// or NULL if the attribute is not present.
|
||||||
|
//
|
||||||
|
// Note that this function returns the components of the Record attribute
|
||||||
|
// even if the class is not a record.
|
||||||
JVM_ENTRY(jobjectArray, JVM_GetRecordComponents(JNIEnv* env, jclass ofClass))
|
JVM_ENTRY(jobjectArray, JVM_GetRecordComponents(JNIEnv* env, jclass ofClass))
|
||||||
{
|
{
|
||||||
JVMWrapper("JVM_GetRecordComponents");
|
JVMWrapper("JVM_GetRecordComponents");
|
||||||
@ -1871,31 +1879,26 @@ JVM_ENTRY(jobjectArray, JVM_GetRecordComponents(JNIEnv* env, jclass ofClass))
|
|||||||
assert(c->is_instance_klass(), "must be");
|
assert(c->is_instance_klass(), "must be");
|
||||||
InstanceKlass* ik = InstanceKlass::cast(c);
|
InstanceKlass* ik = InstanceKlass::cast(c);
|
||||||
|
|
||||||
if (ik->is_record()) {
|
Array<RecordComponent*>* components = ik->record_components();
|
||||||
Array<RecordComponent*>* components = ik->record_components();
|
if (components != NULL) {
|
||||||
assert(components != NULL, "components should not be NULL");
|
JvmtiVMObjectAllocEventCollector oam;
|
||||||
{
|
constantPoolHandle cp(THREAD, ik->constants());
|
||||||
JvmtiVMObjectAllocEventCollector oam;
|
int length = components->length();
|
||||||
constantPoolHandle cp(THREAD, ik->constants());
|
assert(length >= 0, "unexpected record_components length");
|
||||||
int length = components->length();
|
objArrayOop record_components =
|
||||||
assert(length >= 0, "unexpected record_components length");
|
oopFactory::new_objArray(SystemDictionary::RecordComponent_klass(), length, CHECK_NULL);
|
||||||
objArrayOop record_components =
|
objArrayHandle components_h (THREAD, record_components);
|
||||||
oopFactory::new_objArray(SystemDictionary::RecordComponent_klass(), length, CHECK_NULL);
|
|
||||||
objArrayHandle components_h (THREAD, record_components);
|
|
||||||
|
|
||||||
for (int x = 0; x < length; x++) {
|
for (int x = 0; x < length; x++) {
|
||||||
RecordComponent* component = components->at(x);
|
RecordComponent* component = components->at(x);
|
||||||
assert(component != NULL, "unexpected NULL record component");
|
assert(component != NULL, "unexpected NULL record component");
|
||||||
oop component_oop = java_lang_reflect_RecordComponent::create(ik, component, CHECK_NULL);
|
oop component_oop = java_lang_reflect_RecordComponent::create(ik, component, CHECK_NULL);
|
||||||
components_h->obj_at_put(x, component_oop);
|
components_h->obj_at_put(x, component_oop);
|
||||||
}
|
|
||||||
return (jobjectArray)JNIHandles::make_local(THREAD, components_h());
|
|
||||||
}
|
}
|
||||||
|
return (jobjectArray)JNIHandles::make_local(THREAD, components_h());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return empty array if ofClass is not a record.
|
return NULL;
|
||||||
objArrayOop result = oopFactory::new_objArray(SystemDictionary::RecordComponent_klass(), 0, CHECK_NULL);
|
|
||||||
return (jobjectArray)JNIHandles::make_local(THREAD, result);
|
|
||||||
}
|
}
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
@ -2383,11 +2383,7 @@ public final class Class<T> implements java.io.Serializable,
|
|||||||
if (!isRecord()) {
|
if (!isRecord()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
RecordComponent[] recordComponents = getRecordComponents0();
|
return getRecordComponents0();
|
||||||
if (recordComponents == null) {
|
|
||||||
return new RecordComponent[0];
|
|
||||||
}
|
|
||||||
return recordComponents;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3577,9 +3573,17 @@ public final class Class<T> implements java.io.Serializable,
|
|||||||
private native Field[] getDeclaredFields0(boolean publicOnly);
|
private native Field[] getDeclaredFields0(boolean publicOnly);
|
||||||
private native Method[] getDeclaredMethods0(boolean publicOnly);
|
private native Method[] getDeclaredMethods0(boolean publicOnly);
|
||||||
private native Constructor<T>[] getDeclaredConstructors0(boolean publicOnly);
|
private native Constructor<T>[] getDeclaredConstructors0(boolean publicOnly);
|
||||||
private native Class<?>[] getDeclaredClasses0();
|
private native Class<?>[] getDeclaredClasses0();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns an array containing the components of the Record attribute,
|
||||||
|
* or null if the attribute is not present.
|
||||||
|
*
|
||||||
|
* Note that this method returns non-null array on a class with
|
||||||
|
* the Record attribute even if this class is not a record.
|
||||||
|
*/
|
||||||
private native RecordComponent[] getRecordComponents0();
|
private native RecordComponent[] getRecordComponents0();
|
||||||
private native boolean isRecord0();
|
private native boolean isRecord0();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to get the method name from arguments.
|
* Helper method to get the method name from arguments.
|
||||||
@ -3706,6 +3710,8 @@ public final class Class<T> implements java.io.Serializable,
|
|||||||
* @since 16
|
* @since 16
|
||||||
*/
|
*/
|
||||||
public boolean isRecord() {
|
public boolean isRecord() {
|
||||||
|
// this superclass and final modifier check is not strictly necessary
|
||||||
|
// they are intrinsified and serve as a fast-path check
|
||||||
return getSuperclass() == java.lang.Record.class &&
|
return getSuperclass() == java.lang.Record.class &&
|
||||||
(this.getModifiers() & Modifier.FINAL) != 0 &&
|
(this.getModifiers() & Modifier.FINAL) != 0 &&
|
||||||
isRecord0();
|
isRecord0();
|
||||||
|
Loading…
Reference in New Issue
Block a user