--- a/hotspot/src/share/vm/runtime/reflection.cpp Tue Dec 08 05:50:46 2015 -0800
+++ b/hotspot/src/share/vm/runtime/reflection.cpp Tue Dec 08 20:04:03 2015 +0100
@@ -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 @@
}
}
-
-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 @@
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 @@
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 @@
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 @@
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 @@
}
// 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 @@
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 @@
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 @@
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 @@
}
-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 @@
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);
+}
-oop Reflection::invoke(instanceKlassHandle klass, const methodHandle& reflected_method,
- Handle receiver, bool override, objArrayHandle ptypes,
- BasicType rtype, objArrayHandle args, bool is_method_invoke, TRAPS) {
+// 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) {
+
ResourceMark rm(THREAD);
methodHandle method; // actual method to invoke
@@ -876,18 +920,18 @@
// 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 @@
// 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 @@
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 @@
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 @@
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 @@
}
}
- 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 @@
// 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 @@
&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