hotspot/src/share/vm/runtime/sharedRuntime.cpp
changeset 36508 5f9eee6b383b
parent 36331 eeeb86fd9922
child 37179 4dbcb3a642d2
--- 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<char*>(objName);
+    message = const_cast<char*>(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;
 }