8336468: Reflection and MethodHandles should use more precise initializer checks

Reviewed-by: liach, coleenp
This commit is contained in:
Aleksey Shipilev 2024-09-26 15:14:21 +00:00
parent e36ce5f034
commit 376056ca48
5 changed files with 30 additions and 25 deletions

View File

@ -3052,9 +3052,10 @@ void java_lang_ClassFrameInfo::serialize_offsets(SerializeClosure* f) {
static int get_flags(const methodHandle& m) {
int flags = (jushort)( m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS );
if (m->is_initializer()) {
if (m->is_object_initializer()) {
flags |= java_lang_invoke_MemberName::MN_IS_CONSTRUCTOR;
} else {
// Note: Static initializers can be here. Record them as plain methods.
flags |= java_lang_invoke_MemberName::MN_IS_METHOD;
}
if (m->caller_sensitive()) {

View File

@ -444,9 +444,11 @@ JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID meth
methodHandle m (THREAD, Method::resolve_jmethod_id(method_id));
assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match");
oop reflection_method;
if (m->is_initializer()) {
if (m->is_object_initializer()) {
reflection_method = Reflection::new_constructor(m, CHECK_NULL);
} else {
// Note: Static initializers can theoretically be here, if JNI users manage
// to get their jmethodID. Record them as plain methods.
reflection_method = Reflection::new_method(m, false, CHECK_NULL);
}
ret = JNIHandles::make_local(THREAD, reflection_method);

View File

@ -1826,14 +1826,6 @@ JVM_ENTRY(jobjectArray, JVM_GetRecordComponents(JNIEnv* env, jclass ofClass))
}
JVM_END
static bool select_method(const methodHandle& method, bool want_constructor) {
if (want_constructor) {
return (method->is_initializer() && !method->is_static());
} else {
return (!method->is_initializer() && !method->is_overpass());
}
}
static jobjectArray get_class_declared_methods_helper(
JNIEnv *env,
jclass ofClass, jboolean publicOnly,
@ -1866,15 +1858,23 @@ static jobjectArray get_class_declared_methods_helper(
GrowableArray<int>* idnums = new GrowableArray<int>(methods_length);
int num_methods = 0;
// Select methods matching the criteria.
for (int i = 0; i < methods_length; i++) {
methodHandle method(THREAD, methods->at(i));
if (select_method(method, want_constructor)) {
if (!publicOnly || method->is_public()) {
Method* method = methods->at(i);
if (want_constructor && !method->is_object_initializer()) {
continue;
}
if (!want_constructor &&
(method->is_object_initializer() || method->is_static_initializer() ||
method->is_overpass())) {
continue;
}
if (publicOnly && !method->is_public()) {
continue;
}
idnums->push(method->method_idnum());
++num_methods;
}
}
}
// Allocate result
objArrayOop r = oopFactory::new_objArray(klass, num_methods, CHECK_NULL);
@ -2175,10 +2175,11 @@ static jobject get_method_at_helper(const constantPoolHandle& cp, jint index, bo
THROW_MSG_NULL(vmSymbols::java_lang_RuntimeException(), "Unable to look up method in target class");
}
oop method;
if (!m->is_initializer() || m->is_static()) {
method = Reflection::new_method(m, true, CHECK_NULL);
} else {
if (m->is_object_initializer()) {
method = Reflection::new_constructor(m, CHECK_NULL);
} else {
// new_method accepts <clinit> as Method here
method = Reflection::new_method(m, true, CHECK_NULL);
}
return JNIHandles::make_local(THREAD, method);
}

View File

@ -313,8 +313,9 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) {
case CallInfo::direct_call:
vmindex = Method::nonvirtual_vtable_index;
if (m->is_static()) {
assert(!m->is_static_initializer(), "Cannot be static initializer");
flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT);
} else if (m->is_initializer()) {
} else if (m->is_object_initializer()) {
flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
} else {
// "special" reflects that this is a direct call, not that it

View File

@ -766,10 +766,10 @@ static Handle new_type(Symbol* signature, Klass* k, TRAPS) {
}
oop Reflection::new_method(const methodHandle& method, bool for_constant_pool_access, TRAPS) {
// Allow sun.reflect.ConstantPool to refer to <clinit> methods as java.lang.reflect.Methods.
assert(!method()->is_initializer() ||
(for_constant_pool_access && method()->is_static()),
"should call new_constructor instead");
// Allow jdk.internal.reflect.ConstantPool to refer to <clinit> methods as java.lang.reflect.Methods.
assert(!method()->is_object_initializer() &&
(for_constant_pool_access || !method()->is_static_initializer()),
"Should not be the initializer");
InstanceKlass* holder = method->method_holder();
int slot = method->method_idnum();
@ -817,7 +817,7 @@ oop Reflection::new_method(const methodHandle& method, bool for_constant_pool_ac
oop Reflection::new_constructor(const methodHandle& method, TRAPS) {
assert(method()->is_initializer(), "should call new_method instead");
assert(method()->is_object_initializer(), "Should be the initializer");
InstanceKlass* holder = method->method_holder();
int slot = method->method_idnum();