mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8140485: Class load and creation cleanup
Reviewed-by: hseigel, coleenp, sspitsyn
This commit is contained in:
parent
24c8c40bb8
commit
2ad9d3192f
59 changed files with 4174 additions and 3258 deletions
|
@ -46,7 +46,7 @@
|
|||
#include "runtime/signature.hpp"
|
||||
#include "runtime/vframe.hpp"
|
||||
|
||||
static void trace_class_resolution(Klass* to_class) {
|
||||
static void trace_class_resolution(const Klass* to_class) {
|
||||
ResourceMark rm;
|
||||
int line_number = -1;
|
||||
const char * source_file = NULL;
|
||||
|
@ -300,23 +300,23 @@ void Reflection::array_set(jvalue* value, arrayOop a, int index, BasicType value
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
Klass* Reflection::basic_type_mirror_to_arrayklass(oop basic_type_mirror, TRAPS) {
|
||||
static Klass* basic_type_mirror_to_arrayklass(oop basic_type_mirror, TRAPS) {
|
||||
assert(java_lang_Class::is_primitive(basic_type_mirror), "just checking");
|
||||
BasicType type = java_lang_Class::primitive_type(basic_type_mirror);
|
||||
if (type == T_VOID) {
|
||||
THROW_0(vmSymbols::java_lang_IllegalArgumentException());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return Universe::typeArrayKlassObj(type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
oop Reflection:: basic_type_arrayklass_to_mirror(Klass* basic_type_arrayklass, TRAPS) {
|
||||
#ifdef ASSERT
|
||||
static oop basic_type_arrayklass_to_mirror(Klass* basic_type_arrayklass, TRAPS) {
|
||||
BasicType type = TypeArrayKlass::cast(basic_type_arrayklass)->element_type();
|
||||
return Universe::java_mirror(type);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
arrayOop Reflection::reflect_new_array(oop element_mirror, jint length, TRAPS) {
|
||||
if (element_mirror == NULL) {
|
||||
|
@ -410,8 +410,51 @@ oop Reflection::array_component_type(oop mirror, TRAPS) {
|
|||
return result;
|
||||
}
|
||||
|
||||
static bool under_host_klass(const InstanceKlass* ik, const Klass* host_klass) {
|
||||
DEBUG_ONLY(int inf_loop_check = 1000 * 1000 * 1000);
|
||||
for (;;) {
|
||||
const Klass* hc = (const Klass*)ik->host_klass();
|
||||
if (hc == NULL) return false;
|
||||
if (hc == host_klass) return true;
|
||||
ik = InstanceKlass::cast(hc);
|
||||
|
||||
bool Reflection::verify_class_access(Klass* current_class, Klass* new_class, bool classloader_only) {
|
||||
// There's no way to make a host class loop short of patching memory.
|
||||
// Therefore there cannot be a loop here unless there's another bug.
|
||||
// Still, let's check for it.
|
||||
assert(--inf_loop_check > 0, "no host_klass loop");
|
||||
}
|
||||
}
|
||||
|
||||
static bool can_relax_access_check_for(const Klass* accessor,
|
||||
const Klass* accessee,
|
||||
bool classloader_only) {
|
||||
|
||||
const InstanceKlass* accessor_ik = InstanceKlass::cast(accessor);
|
||||
const InstanceKlass* accessee_ik = InstanceKlass::cast(accessee);
|
||||
|
||||
// If either is on the other's host_klass chain, access is OK,
|
||||
// because one is inside the other.
|
||||
if (under_host_klass(accessor_ik, accessee) ||
|
||||
under_host_klass(accessee_ik, accessor))
|
||||
return true;
|
||||
|
||||
if ((RelaxAccessControlCheck &&
|
||||
accessor_ik->major_version() < Verifier::NO_RELAX_ACCESS_CTRL_CHECK_VERSION &&
|
||||
accessee_ik->major_version() < Verifier::NO_RELAX_ACCESS_CTRL_CHECK_VERSION) ||
|
||||
(accessor_ik->major_version() < Verifier::STRICTER_ACCESS_CTRL_CHECK_VERSION &&
|
||||
accessee_ik->major_version() < Verifier::STRICTER_ACCESS_CTRL_CHECK_VERSION)) {
|
||||
return classloader_only &&
|
||||
Verifier::relax_verify_for(accessor_ik->class_loader()) &&
|
||||
accessor_ik->protection_domain() == accessee_ik->protection_domain() &&
|
||||
accessor_ik->class_loader() == accessee_ik->class_loader();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Reflection::verify_class_access(const Klass* current_class,
|
||||
const Klass* new_class,
|
||||
bool classloader_only) {
|
||||
// Verify that current_class can access new_class. If the classloader_only
|
||||
// flag is set, we automatically allow any accesses in which current_class
|
||||
// doesn't have a classloader.
|
||||
|
@ -430,49 +473,9 @@ bool Reflection::verify_class_access(Klass* current_class, Klass* new_class, boo
|
|||
return can_relax_access_check_for(current_class, new_class, classloader_only);
|
||||
}
|
||||
|
||||
static bool under_host_klass(InstanceKlass* ik, Klass* host_klass) {
|
||||
DEBUG_ONLY(int inf_loop_check = 1000 * 1000 * 1000);
|
||||
for (;;) {
|
||||
Klass* hc = (Klass*) ik->host_klass();
|
||||
if (hc == NULL) return false;
|
||||
if (hc == host_klass) return true;
|
||||
ik = InstanceKlass::cast(hc);
|
||||
|
||||
// There's no way to make a host class loop short of patching memory.
|
||||
// Therefore there cannot be a loop here unless there's another bug.
|
||||
// Still, let's check for it.
|
||||
assert(--inf_loop_check > 0, "no host_klass loop");
|
||||
}
|
||||
}
|
||||
|
||||
bool Reflection::can_relax_access_check_for(
|
||||
Klass* accessor, Klass* accessee, bool classloader_only) {
|
||||
InstanceKlass* accessor_ik = InstanceKlass::cast(accessor);
|
||||
InstanceKlass* accessee_ik = InstanceKlass::cast(accessee);
|
||||
|
||||
// If either is on the other's host_klass chain, access is OK,
|
||||
// because one is inside the other.
|
||||
if (under_host_klass(accessor_ik, accessee) ||
|
||||
under_host_klass(accessee_ik, accessor))
|
||||
return true;
|
||||
|
||||
if ((RelaxAccessControlCheck &&
|
||||
accessor_ik->major_version() < Verifier::NO_RELAX_ACCESS_CTRL_CHECK_VERSION &&
|
||||
accessee_ik->major_version() < Verifier::NO_RELAX_ACCESS_CTRL_CHECK_VERSION) ||
|
||||
(accessor_ik->major_version() < Verifier::STRICTER_ACCESS_CTRL_CHECK_VERSION &&
|
||||
accessee_ik->major_version() < Verifier::STRICTER_ACCESS_CTRL_CHECK_VERSION)) {
|
||||
return classloader_only &&
|
||||
Verifier::relax_verify_for(accessor_ik->class_loader()) &&
|
||||
accessor_ik->protection_domain() == accessee_ik->protection_domain() &&
|
||||
accessor_ik->class_loader() == accessee_ik->class_loader();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Reflection::verify_field_access(Klass* current_class,
|
||||
Klass* resolved_class,
|
||||
Klass* field_class,
|
||||
bool Reflection::verify_field_access(const Klass* current_class,
|
||||
const Klass* resolved_class,
|
||||
const Klass* field_class,
|
||||
AccessFlags access,
|
||||
bool classloader_only,
|
||||
bool protected_restriction) {
|
||||
|
@ -494,10 +497,10 @@ bool Reflection::verify_field_access(Klass* current_class,
|
|||
return true;
|
||||
}
|
||||
|
||||
Klass* host_class = current_class;
|
||||
const Klass* host_class = current_class;
|
||||
while (host_class->is_instance_klass() &&
|
||||
InstanceKlass::cast(host_class)->is_anonymous()) {
|
||||
Klass* next_host_class = InstanceKlass::cast(host_class)->host_klass();
|
||||
const Klass* next_host_class = InstanceKlass::cast(host_class)->host_klass();
|
||||
if (next_host_class == NULL) break;
|
||||
host_class = next_host_class;
|
||||
}
|
||||
|
@ -535,16 +538,10 @@ bool Reflection::verify_field_access(Klass* current_class,
|
|||
current_class, field_class, classloader_only);
|
||||
}
|
||||
|
||||
|
||||
bool Reflection::is_same_class_package(Klass* class1, Klass* class2) {
|
||||
bool Reflection::is_same_class_package(const Klass* class1, const Klass* class2) {
|
||||
return InstanceKlass::cast(class1)->is_same_class_package(class2);
|
||||
}
|
||||
|
||||
bool Reflection::is_same_package_member(Klass* class1, Klass* class2, TRAPS) {
|
||||
return InstanceKlass::cast(class1)->is_same_package_member(class2, THREAD);
|
||||
}
|
||||
|
||||
|
||||
// Checks that the 'outer' klass has declared 'inner' as being an inner klass. If not,
|
||||
// throw an incompatible class change exception
|
||||
// If inner_is_member, require the inner to be a member of the outer.
|
||||
|
@ -588,38 +585,43 @@ void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassH
|
|||
}
|
||||
|
||||
// Utility method converting a single SignatureStream element into java.lang.Class instance
|
||||
static oop get_mirror_from_signature(methodHandle method,
|
||||
SignatureStream* ss,
|
||||
TRAPS) {
|
||||
|
||||
oop get_mirror_from_signature(methodHandle method, SignatureStream* ss, TRAPS) {
|
||||
switch (ss->type()) {
|
||||
default:
|
||||
assert(ss->type() != T_VOID || ss->at_return_type(), "T_VOID should only appear as return type");
|
||||
return java_lang_Class::primitive_mirror(ss->type());
|
||||
case T_OBJECT:
|
||||
case T_ARRAY:
|
||||
Symbol* name = ss->as_symbol(CHECK_NULL);
|
||||
oop loader = method->method_holder()->class_loader();
|
||||
oop protection_domain = method->method_holder()->protection_domain();
|
||||
Klass* k = SystemDictionary::resolve_or_fail(
|
||||
name,
|
||||
Handle(THREAD, loader),
|
||||
Handle(THREAD, protection_domain),
|
||||
true, CHECK_NULL);
|
||||
if (TraceClassResolution) {
|
||||
trace_class_resolution(k);
|
||||
}
|
||||
return k->java_mirror();
|
||||
};
|
||||
|
||||
if (T_OBJECT == ss->type() || T_ARRAY == ss->type()) {
|
||||
Symbol* name = ss->as_symbol(CHECK_NULL);
|
||||
oop loader = method->method_holder()->class_loader();
|
||||
oop protection_domain = method->method_holder()->protection_domain();
|
||||
const Klass* k = SystemDictionary::resolve_or_fail(name,
|
||||
Handle(THREAD, loader),
|
||||
Handle(THREAD, protection_domain),
|
||||
true,
|
||||
CHECK_NULL);
|
||||
if (TraceClassResolution) {
|
||||
trace_class_resolution(k);
|
||||
}
|
||||
return k->java_mirror();
|
||||
}
|
||||
|
||||
assert(ss->type() != T_VOID || ss->at_return_type(),
|
||||
"T_VOID should only appear as return type");
|
||||
|
||||
return java_lang_Class::primitive_mirror(ss->type());
|
||||
}
|
||||
|
||||
|
||||
objArrayHandle Reflection::get_parameter_types(const methodHandle& method, int parameter_count, oop* return_type, TRAPS) {
|
||||
static objArrayHandle get_parameter_types(methodHandle method,
|
||||
int parameter_count,
|
||||
oop* return_type,
|
||||
TRAPS) {
|
||||
// Allocate array holding parameter types (java.lang.Class instances)
|
||||
objArrayOop m = oopFactory::new_objArray(SystemDictionary::Class_klass(), parameter_count, CHECK_(objArrayHandle()));
|
||||
objArrayHandle mirrors (THREAD, m);
|
||||
objArrayHandle mirrors(THREAD, m);
|
||||
int index = 0;
|
||||
// Collect parameter types
|
||||
ResourceMark rm(THREAD);
|
||||
Symbol* signature = method->signature();
|
||||
Symbol* signature = method->signature();
|
||||
SignatureStream ss(signature);
|
||||
while (!ss.at_return_type()) {
|
||||
oop mirror = get_mirror_from_signature(method, &ss, CHECK_(objArrayHandle()));
|
||||
|
@ -635,22 +637,22 @@ objArrayHandle Reflection::get_parameter_types(const methodHandle& method, int p
|
|||
return mirrors;
|
||||
}
|
||||
|
||||
objArrayHandle Reflection::get_exception_types(const methodHandle& method, TRAPS) {
|
||||
static objArrayHandle get_exception_types(methodHandle method, TRAPS) {
|
||||
return method->resolved_checked_exceptions(THREAD);
|
||||
}
|
||||
|
||||
|
||||
Handle Reflection::new_type(Symbol* signature, KlassHandle k, TRAPS) {
|
||||
static Handle new_type(Symbol* signature, KlassHandle k, TRAPS) {
|
||||
// Basic types
|
||||
BasicType type = vmSymbols::signature_type(signature);
|
||||
if (type != T_OBJECT) {
|
||||
return Handle(THREAD, Universe::java_mirror(type));
|
||||
}
|
||||
|
||||
Klass* result = SystemDictionary::resolve_or_fail(signature,
|
||||
Handle(THREAD, k->class_loader()),
|
||||
Handle(THREAD, k->protection_domain()),
|
||||
true, CHECK_(Handle()));
|
||||
Klass* result =
|
||||
SystemDictionary::resolve_or_fail(signature,
|
||||
Handle(THREAD, k->class_loader()),
|
||||
Handle(THREAD, k->protection_domain()),
|
||||
true, CHECK_(Handle()));
|
||||
|
||||
if (TraceClassResolution) {
|
||||
trace_class_resolution(result);
|
||||
|
@ -686,7 +688,7 @@ oop Reflection::new_method(const methodHandle& method, bool for_constant_pool_ac
|
|||
Handle name = Handle(THREAD, name_oop);
|
||||
if (name == NULL) return NULL;
|
||||
|
||||
int modifiers = method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS;
|
||||
const int modifiers = method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS;
|
||||
|
||||
Handle mh = java_lang_reflect_Method::create(CHECK_NULL);
|
||||
|
||||
|
@ -738,7 +740,7 @@ oop Reflection::new_constructor(const methodHandle& method, TRAPS) {
|
|||
objArrayHandle exception_types = get_exception_types(method, CHECK_NULL);
|
||||
if (exception_types.is_null()) return NULL;
|
||||
|
||||
int modifiers = method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS;
|
||||
const int modifiers = method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS;
|
||||
|
||||
Handle ch = java_lang_reflect_Constructor::create(CHECK_NULL);
|
||||
|
||||
|
@ -822,8 +824,12 @@ oop Reflection::new_parameter(Handle method, int index, Symbol* sym,
|
|||
}
|
||||
|
||||
|
||||
methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, const methodHandle& method,
|
||||
KlassHandle recv_klass, Handle receiver, TRAPS) {
|
||||
static methodHandle resolve_interface_call(instanceKlassHandle klass,
|
||||
const methodHandle& method,
|
||||
KlassHandle recv_klass,
|
||||
Handle receiver,
|
||||
TRAPS) {
|
||||
|
||||
assert(!method.is_null() , "method should not be null");
|
||||
|
||||
CallInfo info;
|
||||
|
@ -836,10 +842,48 @@ methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, const
|
|||
return info.selected_method();
|
||||
}
|
||||
|
||||
// Conversion
|
||||
static BasicType basic_type_mirror_to_basic_type(oop basic_type_mirror, TRAPS) {
|
||||
assert(java_lang_Class::is_primitive(basic_type_mirror),
|
||||
"just checking");
|
||||
return java_lang_Class::primitive_type(basic_type_mirror);
|
||||
}
|
||||
|
||||
// Narrowing of basic types. Used to create correct jvalues for
|
||||
// boolean, byte, char and short return return values from interpreter
|
||||
// which are returned as ints. Throws IllegalArgumentException.
|
||||
static void narrow(jvalue* value, BasicType narrow_type, TRAPS) {
|
||||
switch (narrow_type) {
|
||||
case T_BOOLEAN:
|
||||
value->z = (jboolean)value->i;
|
||||
return;
|
||||
case T_BYTE:
|
||||
value->b = (jbyte)value->i;
|
||||
return;
|
||||
case T_CHAR:
|
||||
value->c = (jchar)value->i;
|
||||
return;
|
||||
case T_SHORT:
|
||||
value->s = (jshort)value->i;
|
||||
return;
|
||||
default:
|
||||
break; // fail
|
||||
}
|
||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch");
|
||||
}
|
||||
|
||||
|
||||
// Method call (shared by invoke_method and invoke_constructor)
|
||||
static oop invoke(instanceKlassHandle klass,
|
||||
methodHandle reflected_method,
|
||||
Handle receiver,
|
||||
bool override,
|
||||
objArrayHandle ptypes,
|
||||
BasicType rtype,
|
||||
objArrayHandle args,
|
||||
bool is_method_invoke,
|
||||
TRAPS) {
|
||||
|
||||
oop Reflection::invoke(instanceKlassHandle klass, const methodHandle& reflected_method,
|
||||
Handle receiver, bool override, objArrayHandle ptypes,
|
||||
BasicType rtype, objArrayHandle args, bool is_method_invoke, TRAPS) {
|
||||
ResourceMark rm(THREAD);
|
||||
|
||||
methodHandle method; // actual method to invoke
|
||||
|
@ -876,18 +920,18 @@ oop Reflection::invoke(instanceKlassHandle klass, const methodHandle& reflected_
|
|||
// Linktime resolution & IllegalAccessCheck already done by Class.getMethod()
|
||||
method = resolve_interface_call(klass, reflected_method, target_klass, receiver, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
// Method resolution threw an exception; wrap it in an InvocationTargetException
|
||||
// Method resolution threw an exception; wrap it in an InvocationTargetException
|
||||
oop resolution_exception = PENDING_EXCEPTION;
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
// JVMTI has already reported the pending exception
|
||||
// JVMTI internal flag reset is needed in order to report InvocationTargetException
|
||||
if (THREAD->is_Java_thread()) {
|
||||
JvmtiExport::clear_detected_exception((JavaThread*) THREAD);
|
||||
JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
|
||||
}
|
||||
JavaCallArguments args(Handle(THREAD, resolution_exception));
|
||||
THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(),
|
||||
vmSymbols::throwable_void_signature(),
|
||||
&args);
|
||||
vmSymbols::throwable_void_signature(),
|
||||
&args);
|
||||
}
|
||||
} else {
|
||||
// if the method can be overridden, we resolve using the vtable index.
|
||||
|
@ -906,10 +950,10 @@ oop Reflection::invoke(instanceKlassHandle klass, const methodHandle& reflected_
|
|||
// new default: 6531596
|
||||
ResourceMark rm(THREAD);
|
||||
Handle h_origexception = Exceptions::new_exception(THREAD,
|
||||
vmSymbols::java_lang_AbstractMethodError(),
|
||||
Method::name_and_sig_as_C_string(target_klass(),
|
||||
method->name(),
|
||||
method->signature()));
|
||||
vmSymbols::java_lang_AbstractMethodError(),
|
||||
Method::name_and_sig_as_C_string(target_klass(),
|
||||
method->name(),
|
||||
method->signature()));
|
||||
JavaCallArguments args(h_origexception);
|
||||
THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(),
|
||||
vmSymbols::throwable_void_signature(),
|
||||
|
@ -926,15 +970,16 @@ oop Reflection::invoke(instanceKlassHandle klass, const methodHandle& reflected_
|
|||
ResourceMark rm(THREAD);
|
||||
THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(),
|
||||
Method::name_and_sig_as_C_string(klass(),
|
||||
reflected_method->name(),
|
||||
reflected_method->signature()));
|
||||
reflected_method->name(),
|
||||
reflected_method->signature()));
|
||||
}
|
||||
|
||||
assert(ptypes->is_objArray(), "just checking");
|
||||
int args_len = args.is_null() ? 0 : args->length();
|
||||
// Check number of arguments
|
||||
if (ptypes->length() != args_len) {
|
||||
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "wrong number of arguments");
|
||||
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
|
||||
"wrong number of arguments");
|
||||
}
|
||||
|
||||
// Create object to contain parameters for the JavaCall
|
||||
|
@ -950,9 +995,9 @@ oop Reflection::invoke(instanceKlassHandle klass, const methodHandle& reflected_
|
|||
if (java_lang_Class::is_primitive(type_mirror)) {
|
||||
jvalue value;
|
||||
BasicType ptype = basic_type_mirror_to_basic_type(type_mirror, CHECK_NULL);
|
||||
BasicType atype = unbox_for_primitive(arg, &value, CHECK_NULL);
|
||||
BasicType atype = Reflection::unbox_for_primitive(arg, &value, CHECK_NULL);
|
||||
if (ptype != atype) {
|
||||
widen(&value, atype, ptype, CHECK_NULL);
|
||||
Reflection::widen(&value, atype, ptype, CHECK_NULL);
|
||||
}
|
||||
switch (ptype) {
|
||||
case T_BOOLEAN: java_args.push_int(value.z); break;
|
||||
|
@ -970,7 +1015,8 @@ oop Reflection::invoke(instanceKlassHandle klass, const methodHandle& reflected_
|
|||
if (arg != NULL) {
|
||||
Klass* k = java_lang_Class::as_Klass(type_mirror);
|
||||
if (!arg->is_a(k)) {
|
||||
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch");
|
||||
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
|
||||
"argument type mismatch");
|
||||
}
|
||||
}
|
||||
Handle arg_handle(THREAD, arg); // Create handle for argument
|
||||
|
@ -978,7 +1024,8 @@ oop Reflection::invoke(instanceKlassHandle klass, const methodHandle& reflected_
|
|||
}
|
||||
}
|
||||
|
||||
assert(java_args.size_of_parameters() == method->size_of_parameters(), "just checking");
|
||||
assert(java_args.size_of_parameters() == method->size_of_parameters(),
|
||||
"just checking");
|
||||
|
||||
// All oops (including receiver) is passed in as Handles. An potential oop is returned as an
|
||||
// oop (i.e., NOT as an handle)
|
||||
|
@ -992,7 +1039,7 @@ oop Reflection::invoke(instanceKlassHandle klass, const methodHandle& reflected_
|
|||
// JVMTI has already reported the pending exception
|
||||
// JVMTI internal flag reset is needed in order to report InvocationTargetException
|
||||
if (THREAD->is_Java_thread()) {
|
||||
JvmtiExport::clear_detected_exception((JavaThread*) THREAD);
|
||||
JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
|
||||
}
|
||||
|
||||
JavaCallArguments args(Handle(THREAD, target_exception));
|
||||
|
@ -1001,39 +1048,12 @@ oop Reflection::invoke(instanceKlassHandle klass, const methodHandle& reflected_
|
|||
&args);
|
||||
} else {
|
||||
if (rtype == T_BOOLEAN || rtype == T_BYTE || rtype == T_CHAR || rtype == T_SHORT) {
|
||||
narrow((jvalue*) result.get_value_addr(), rtype, CHECK_NULL);
|
||||
narrow((jvalue*)result.get_value_addr(), rtype, CHECK_NULL);
|
||||
}
|
||||
return box((jvalue*) result.get_value_addr(), rtype, THREAD);
|
||||
return Reflection::box((jvalue*)result.get_value_addr(), rtype, THREAD);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Reflection::narrow(jvalue* value, BasicType narrow_type, TRAPS) {
|
||||
switch (narrow_type) {
|
||||
case T_BOOLEAN:
|
||||
value->z = (jboolean) value->i;
|
||||
return;
|
||||
case T_BYTE:
|
||||
value->b = (jbyte) value->i;
|
||||
return;
|
||||
case T_CHAR:
|
||||
value->c = (jchar) value->i;
|
||||
return;
|
||||
case T_SHORT:
|
||||
value->s = (jshort) value->i;
|
||||
return;
|
||||
default:
|
||||
break; // fail
|
||||
}
|
||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch");
|
||||
}
|
||||
|
||||
|
||||
BasicType Reflection::basic_type_mirror_to_basic_type(oop basic_type_mirror, TRAPS) {
|
||||
assert(java_lang_Class::is_primitive(basic_type_mirror), "just checking");
|
||||
return java_lang_Class::primitive_type(basic_type_mirror);
|
||||
}
|
||||
|
||||
// This would be nicer if, say, java.lang.reflect.Method was a subclass
|
||||
// of java.lang.reflect.Constructor
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue