diff -r c80f6ecb0bb3 -r 5f9eee6b383b hotspot/src/share/vm/runtime/sharedRuntime.cpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Tue Mar 15 13:48:21 2016 -0700 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Mar 17 19:04:01 2016 +0000 @@ -39,6 +39,8 @@ #include "interpreter/interpreterRuntime.hpp" #include "logging/log.hpp" #include "memory/universe.inline.hpp" +#include "oops/klass.hpp" +#include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" #include "prims/forte.hpp" #include "prims/jvmtiExport.hpp" @@ -1915,28 +1917,58 @@ } JRT_END +// The caller of generate_class_cast_message() (or one of its callers) +// must use a ResourceMark in order to correctly free the result. char* SharedRuntime::generate_class_cast_message( - JavaThread* thread, const char* objName) { + JavaThread* thread, Klass* caster_klass) { // Get target class name from the checkcast instruction vframeStream vfst(thread, true); assert(!vfst.at_end(), "Java frame must exist"); Bytecode_checkcast cc(vfst.method(), vfst.method()->bcp_from(vfst.bci())); - Klass* targetKlass = vfst.method()->constants()->klass_at( + Klass* target_klass = vfst.method()->constants()->klass_at( cc.index(), thread); - return generate_class_cast_message(objName, targetKlass->external_name()); + return generate_class_cast_message(caster_klass, target_klass); } char* SharedRuntime::generate_class_cast_message( - const char* objName, const char* targetKlassName, const char* desc) { - size_t msglen = strlen(objName) + strlen(desc) + strlen(targetKlassName) + 1; + Klass* caster_klass, Klass* target_klass) { + + const char* caster_klass_name = caster_klass->external_name(); + Klass* c_klass = caster_klass->is_objArray_klass() ? + ObjArrayKlass::cast(caster_klass)->bottom_klass() : caster_klass; + ModuleEntry* caster_module; + const char* caster_module_name; + if (c_klass->is_instance_klass()) { + caster_module = InstanceKlass::cast(c_klass)->module(); + caster_module_name = caster_module->is_named() ? + caster_module->name()->as_C_string() : UNNAMED_MODULE; + } else { + caster_module_name = "java.base"; + } + const char* target_klass_name = target_klass->external_name(); + Klass* t_klass = target_klass->is_objArray_klass() ? + ObjArrayKlass::cast(target_klass)->bottom_klass() : target_klass; + ModuleEntry* target_module; + const char* target_module_name; + if (t_klass->is_instance_klass()) { + target_module = InstanceKlass::cast(t_klass)->module(); + target_module_name = target_module->is_named() ? + target_module->name()->as_C_string(): UNNAMED_MODULE; + } else { + target_module_name = "java.base"; + } + + size_t msglen = strlen(caster_klass_name) + strlen(caster_module_name) + + strlen(target_klass_name) + strlen(target_module_name) + 50; char* message = NEW_RESOURCE_ARRAY(char, msglen); if (NULL == message) { // Shouldn't happen, but don't cause even more problems if it does - message = const_cast(objName); + message = const_cast(caster_klass_name); } else { - jio_snprintf(message, msglen, "%s%s%s", objName, desc, targetKlassName); + jio_snprintf(message, msglen, "%s (in module: %s) cannot be cast to %s (in module: %s)", + caster_klass_name, caster_module_name, target_klass_name, target_module_name); } return message; }