8169559: Add class loader names to relevant VM messages
authorlfoltan
Mon, 25 Jun 2018 11:33:11 -0400
changeset 50761 cb07f4b539fc
parent 50760 8e296de294e7
child 50762 3c3ff151c75e
child 56807 b9e374d0534f
8169559: Add class loader names to relevant VM messages Summary: Added new method class_in_module_of_loader to provide a standard format for class information within error messages. Reviewed-by: goetz, hseigel, mchung
src/hotspot/share/classfile/classFileParser.cpp
src/hotspot/share/classfile/moduleEntry.hpp
src/hotspot/share/interpreter/linkResolver.cpp
src/hotspot/share/oops/instanceKlass.cpp
src/hotspot/share/oops/klass.cpp
src/hotspot/share/oops/klass.hpp
src/hotspot/share/runtime/sharedRuntime.cpp
test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/IncompatibleClassChangeErrorTest.java
test/hotspot/jtreg/runtime/modules/AccessCheck/ExpQualToM1PrivateMethodIAE.java
test/hotspot/jtreg/runtime/modules/AccessCheck/p1/c1.jasm
test/hotspot/jtreg/runtime/modules/AccessCheck/p2/c2.jasm
test/hotspot/jtreg/runtime/modules/CCE_module_msg.java
test/hotspot/jtreg/vmTestbase/jit/t/t113/t113.gold
--- a/src/hotspot/share/classfile/classFileParser.cpp	Mon Jun 25 20:36:06 2018 +0530
+++ b/src/hotspot/share/classfile/classFileParser.cpp	Mon Jun 25 11:33:11 2018 -0400
@@ -955,9 +955,10 @@
 
       if (!interf->is_interface()) {
         THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),
-                  err_msg("Class %s can not implement %s, because it is not an interface",
+                  err_msg("class %s can not implement %s, because it is not an interface (%s)",
                           _class_name->as_klass_external_name(),
-                          interf->class_loader_and_module_name()));
+                          interf->external_name(),
+                          interf->class_in_module_of_loader()));
       }
 
       if (InstanceKlass::cast(interf)->has_nonstatic_concrete_methods()) {
--- a/src/hotspot/share/classfile/moduleEntry.hpp	Mon Jun 25 20:36:06 2018 +0530
+++ b/src/hotspot/share/classfile/moduleEntry.hpp	Mon Jun 25 11:33:11 2018 -0400
@@ -40,10 +40,12 @@
 #include "jfr/support/jfrTraceIdExtension.hpp"
 #endif
 
-#define UNNAMED_MODULE "Unnamed Module"
+#define UNNAMED_MODULE "unnamed module"
+#define UNNAMED_MODULE_LEN 14
 #define JAVAPKG "java"
 #define JAVAPKG_LEN 4
 #define JAVA_BASE_NAME "java.base"
+#define JAVA_BASE_NAME_LEN 9
 
 class ModuleClosure;
 
--- a/src/hotspot/share/interpreter/linkResolver.cpp	Mon Jun 25 20:36:06 2018 +0530
+++ b/src/hotspot/share/interpreter/linkResolver.cpp	Mon Jun 25 11:33:11 2018 -0400
@@ -592,14 +592,18 @@
   // from nest-host resolution, have been allowed to propagate.
   if (!can_access) {
     ResourceMark rm(THREAD);
+    bool same_module = (sel_klass->module() == ref_klass->module());
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
       vmSymbols::java_lang_IllegalAccessError(),
-      "tried to access method %s.%s%s from class %s",
+      "class %s tried to access method %s.%s%s (%s%s%s)",
+      ref_klass->external_name(),
       sel_klass->external_name(),
       sel_method->name()->as_C_string(),
       sel_method->signature()->as_C_string(),
-      ref_klass->external_name()
+      (same_module) ? ref_klass->joint_in_module_of_loader(sel_klass) : ref_klass->class_in_module_of_loader(),
+      (same_module) ? "" : "; ",
+      (same_module) ? "" : sel_klass->class_in_module_of_loader()
     );
     return;
   }
--- a/src/hotspot/share/oops/instanceKlass.cpp	Mon Jun 25 20:36:06 2018 +0530
+++ b/src/hotspot/share/oops/instanceKlass.cpp	Mon Jun 25 11:33:11 2018 -0400
@@ -2850,9 +2850,14 @@
     if (cnt >= nof_interfaces) {
       ResourceMark rm(THREAD);
       stringStream ss;
+      bool same_module = (module() == holder->module());
       ss.print("Receiver class %s does not implement "
-               "the interface %s defining the method to be called",
-               class_loader_and_module_name(), holder->class_loader_and_module_name());
+               "the interface %s defining the method to be called "
+               "(%s%s%s)",
+               external_name(), holder->external_name(),
+               (same_module) ? joint_in_module_of_loader(holder) : class_in_module_of_loader(),
+               (same_module) ? "" : "; ",
+               (same_module) ? "" : holder->class_in_module_of_loader());
       THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
     }
 
--- a/src/hotspot/share/oops/klass.cpp	Mon Jun 25 20:36:06 2018 +0530
+++ b/src/hotspot/share/oops/klass.cpp	Mon Jun 25 11:33:11 2018 -0400
@@ -774,80 +774,124 @@
 
 #endif // PRODUCT
 
-// The caller of class_loader_and_module_name() (or one of its callers)
-// must use a ResourceMark in order to correctly free the result.
-const char* Klass::class_loader_and_module_name() const {
-  const char* delim = "/";
-  size_t delim_len = strlen(delim);
-
-  const char* fqn = external_name();
-  // Length of message to return; always include FQN
-  size_t msglen = strlen(fqn) + 1;
-
-  bool has_cl_name = false;
-  bool has_mod_name = false;
-  bool has_version = false;
+// Caller needs ResourceMark
+// joint_in_module_of_loader provides an optimization if 2 classes are in
+// the same module to succinctly print out relevant information about their
+// module name and class loader's name_and_id for error messages.
+// Format:
+//   <fully-qualified-external-class-name1> and <fully-qualified-external-class-name2>
+//                      are in module <module-name>[@<version>]
+//                      of loader <loader-name_and_id>[, parent loader <parent-loader-name_and_id>]
+const char* Klass::joint_in_module_of_loader(const Klass* class2, bool include_parent_loader) const {
+  assert(module() == class2->module(), "classes do not have the same module");
+  const char* class1_name = external_name();
+  size_t len = strlen(class1_name) + 1;
 
-  // Use class loader name, if exists and not builtin
-  const char* class_loader_name = "";
-  ClassLoaderData* cld = class_loader_data();
-  assert(cld != NULL, "class_loader_data should not be NULL");
-  if (!cld->is_builtin_class_loader_data()) {
-    // If not builtin, look for name
-    oop loader = class_loader();
-    if (loader != NULL) {
-      oop class_loader_name_oop = java_lang_ClassLoader::name(loader);
-      if (class_loader_name_oop != NULL) {
-        class_loader_name = java_lang_String::as_utf8_string(class_loader_name_oop);
-        if (class_loader_name != NULL && class_loader_name[0] != '\0') {
-          has_cl_name = true;
-          msglen += strlen(class_loader_name) + delim_len;
-        }
-      }
-    }
+  const char* class2_description = class2->class_in_module_of_loader(true, include_parent_loader);
+  len += strlen(class2_description);
+
+  len += strlen(" and ");
+
+  char* joint_description = NEW_RESOURCE_ARRAY_RETURN_NULL(char, len);
+
+  // Just return the FQN if error when allocating string
+  if (joint_description == NULL) {
+    return class1_name;
   }
 
+  jio_snprintf(joint_description, len, "%s and %s",
+               class1_name,
+               class2_description);
+
+  return joint_description;
+}
+
+// Caller needs ResourceMark
+// class_in_module_of_loader provides a standard way to include
+// relevant information about a class, such as its module name as
+// well as its class loader's name_and_id, in error messages and logging.
+// Format:
+//   <fully-qualified-external-class-name> is in module <module-name>[@<version>]
+//                                         of loader <loader-name_and_id>[, parent loader <parent-loader-name_and_id>]
+const char* Klass::class_in_module_of_loader(bool use_are, bool include_parent_loader) const {
+  // 1. fully qualified external name of class
+  const char* klass_name = external_name();
+  size_t len = strlen(klass_name) + 1;
+
+  // 2. module name + @version
   const char* module_name = "";
   const char* version = "";
+  bool has_version = false;
+  bool module_is_named = false;
+  const char* module_name_phrase = "";
   const Klass* bottom_klass = is_objArray_klass() ?
-    ObjArrayKlass::cast(this)->bottom_klass() : this;
+                                ObjArrayKlass::cast(this)->bottom_klass() : this;
   if (bottom_klass->is_instance_klass()) {
     ModuleEntry* module = InstanceKlass::cast(bottom_klass)->module();
-    // Use module name, if exists
     if (module->is_named()) {
-      has_mod_name = true;
+      module_is_named = true;
+      module_name_phrase = "module ";
       module_name = module->name()->as_C_string();
-      msglen += strlen(module_name);
+      len += strlen(module_name);
       // Use version if exists and is not a jdk module
       if (module->should_show_version()) {
         has_version = true;
         version = module->version()->as_C_string();
-        msglen += strlen(version) + 1; // +1 for "@"
+        // Include stlen(version) + 1 for the "@"
+        len += strlen(version) + 1;
       }
+    } else {
+      module_name = UNNAMED_MODULE;
+      len += UNNAMED_MODULE_LEN;
     }
   } else {
-    // klass is an array of primitives, so its module is java.base
+    // klass is an array of primitives, module is java.base
+    module_is_named = true;
+    module_name_phrase = "module ";
     module_name = JAVA_BASE_NAME;
-  }
-
-  if (has_cl_name || has_mod_name) {
-    msglen += delim_len;
+    len += JAVA_BASE_NAME_LEN;
   }
 
-  char* message = NEW_RESOURCE_ARRAY_RETURN_NULL(char, msglen);
+  // 3. class loader's name_and_id
+  ClassLoaderData* cld = class_loader_data();
+  assert(cld != NULL, "class_loader_data should not be null");
+  const char* loader_name_and_id = cld->loader_name_and_id();
+  len += strlen(loader_name_and_id);
 
-  // Just return the FQN if error in allocating string
-  if (message == NULL) {
-    return fqn;
+  // 4. include parent loader information
+  const char* parent_loader_phrase = "";
+  const char* parent_loader_name_and_id = "";
+  if (include_parent_loader &&
+      !cld->is_builtin_class_loader_data()) {
+    oop parent_loader = java_lang_ClassLoader::parent(class_loader());
+    ClassLoaderData *parent_cld = ClassLoaderData::class_loader_data(parent_loader);
+    assert(parent_cld != NULL, "parent's class loader data should not be null");
+    parent_loader_name_and_id = parent_cld->loader_name_and_id();
+    parent_loader_phrase = ", parent loader ";
+    len += strlen(parent_loader_phrase) + strlen(parent_loader_name_and_id);
   }
 
-  jio_snprintf(message, msglen, "%s%s%s%s%s%s%s",
-               class_loader_name,
-               (has_cl_name) ? delim : "",
-               (has_mod_name) ? module_name : "",
+  // Start to construct final full class description string
+  len += ((use_are) ? strlen(" are in ") : strlen(" is in "));
+  len += strlen(module_name_phrase) + strlen(" of loader ");
+
+  char* class_description = NEW_RESOURCE_ARRAY_RETURN_NULL(char, len);
+
+  // Just return the FQN if error when allocating string
+  if (class_description == NULL) {
+    return klass_name;
+  }
+
+  jio_snprintf(class_description, len, "%s %s in %s%s%s%s of loader %s%s%s",
+               klass_name,
+               (use_are) ? "are" : "is",
+               module_name_phrase,
+               module_name,
                (has_version) ? "@" : "",
                (has_version) ? version : "",
-               (has_cl_name || has_mod_name) ? delim : "",
-               fqn);
-  return message;
+               loader_name_and_id,
+               parent_loader_phrase,
+               parent_loader_name_and_id);
+
+  return class_description;
 }
--- a/src/hotspot/share/oops/klass.hpp	Mon Jun 25 20:36:06 2018 +0530
+++ b/src/hotspot/share/oops/klass.hpp	Mon Jun 25 11:33:11 2018 -0400
@@ -560,7 +560,8 @@
   //     and the package separators as '/'.
   virtual const char* signature_name() const;
 
-  const char* class_loader_and_module_name() const;
+  const char* joint_in_module_of_loader(const Klass* class2, bool include_parent_loader = false) const;
+  const char* class_in_module_of_loader(bool use_are = false, bool include_parent_loader = false) const;
 
   // Returns "interface", "abstract class" or "class".
   const char* external_kind() const;
--- a/src/hotspot/share/runtime/sharedRuntime.cpp	Mon Jun 25 20:36:06 2018 +0530
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp	Mon Jun 25 11:33:11 2018 -0400
@@ -1959,14 +1959,27 @@
 // must use a ResourceMark in order to correctly free the result.
 char* SharedRuntime::generate_class_cast_message(
     Klass* caster_klass, Klass* target_klass, Symbol* target_klass_name) {
-
-  const char* caster_name = caster_klass->class_loader_and_module_name();
+  const char* caster_name = caster_klass->external_name();
 
   assert(target_klass != NULL || target_klass_name != NULL, "one must be provided");
   const char* target_name = target_klass == NULL ? target_klass_name->as_C_string() :
-                                                   target_klass->class_loader_and_module_name();
-
-  size_t msglen = strlen(caster_name) + strlen(" cannot be cast to ") + strlen(target_name) + 1;
+                                                   target_klass->external_name();
+
+  size_t msglen = strlen(caster_name) + strlen("class ") + strlen(" cannot be cast to class ") + strlen(target_name) + 1;
+
+  const char* caster_klass_description = "";
+  const char* target_klass_description = "";
+  const char* klass_separator = "";
+  if (target_klass != NULL && caster_klass->module() == target_klass->module()) {
+    caster_klass_description = caster_klass->joint_in_module_of_loader(target_klass);
+  } else {
+    caster_klass_description = caster_klass->class_in_module_of_loader();
+    target_klass_description = (target_klass != NULL) ? target_klass->class_in_module_of_loader() : "";
+    klass_separator = (target_klass != NULL) ? "; " : "";
+  }
+
+  // add 3 for parenthesis and preceeding space
+  msglen += strlen(caster_klass_description) + strlen(target_klass_description) + strlen(klass_separator) + 3;
 
   char* message = NEW_RESOURCE_ARRAY_RETURN_NULL(char, msglen);
   if (message == NULL) {
@@ -1975,9 +1988,13 @@
   } else {
     jio_snprintf(message,
                  msglen,
-                 "%s cannot be cast to %s",
+                 "class %s cannot be cast to class %s (%s%s%s)",
                  caster_name,
-                 target_name);
+                 target_name,
+                 caster_klass_description,
+                 klass_separator,
+                 target_klass_description
+                 );
   }
   return message;
 }
--- a/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/IncompatibleClassChangeErrorTest.java	Mon Jun 25 20:36:06 2018 +0530
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/IncompatibleClassChangeErrorTest.java	Mon Jun 25 11:33:11 2018 -0400
@@ -212,7 +212,7 @@
     }
 
     private static String expectedErrorMessage3 =
-        "Class test.ICC3_B can not implement test.ICC3_A, because it is not an interface";
+        "class test.ICC3_B can not implement test.ICC3_A, because it is not an interface (test.ICC3_A is in unnamed module of loader 'app')";
 
     public static void test3_implementsClass() throws Exception {
         try {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/modules/AccessCheck/ExpQualToM1PrivateMethodIAE.java	Mon Jun 25 11:33:11 2018 -0400
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test that if module m1x can read module m2x, AND package p2 in m2x is
+ *          exported qualifiedly to m1x, then class p1.c1 in m1x can read p2.c2 in m2x.
+ *          However, p1.c1 tries to access a private method within p2.c2, verify
+ *          that the IAE message contains the correct loader and module names.
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @compile p1/c1.jasm
+ * @compile p2/c2.jasm
+ * @compile myloaders/MySameClassLoader.java
+ * @run main/othervm -Xbootclasspath/a:. ExpQualToM1PrivateMethodIAE
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MySameClassLoader;
+
+public class ExpQualToM1PrivateMethodIAE {
+
+    // Create a layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1x
+        // Can read:          java.base, m2x
+        // Packages:          p1
+        // Packages exported: p1 is exported unqualifiedly
+        ModuleDescriptor descriptor_m1x =
+                ModuleDescriptor.newModule("m1x")
+                        .requires("java.base")
+                        .requires("m2x")
+                        .exports("p1")
+                        .build();
+
+        // Define module:     m2x
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: p2 is exported qualifiedly to m1x
+        ModuleDescriptor descriptor_m2x =
+                ModuleDescriptor.newModule("m2x")
+                        .requires("java.base")
+                        .exports("p2", Set.of("m1x"))
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1x, descriptor_m2x);
+
+        // Resolves "m1x"
+        Configuration cf = ModuleLayer.boot()
+                .configuration()
+                .resolve(finder, ModuleFinder.of(), Set.of("m1x"));
+
+        // map each module to the same class loader for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1x", MySameClassLoader.loader1);
+        map.put("m2x", MySameClassLoader.loader1);
+
+        // Create layer that contains m1x & m2x
+        ModuleLayer layer = ModuleLayer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1x") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("m2x") == MySameClassLoader.loader1);
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = MySameClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+            throw new RuntimeException("Test Failed, an IAE should be thrown since p2/c2's method2 is private");
+        } catch (IllegalAccessError e) {
+            String message = e.getMessage();
+            System.out.println(e.toString());
+            // java.lang.IllegalAccessError:
+            //   tried to access method p2.c2.method2()V from class p1.c1 (p2.c2 is in module m2x of loader
+            //   myloaders.MySameClassLoader @<id>; p1.c1 is in module m1x of loader myloaders.MySameClassLoader @<id>)
+            if (!message.contains("class p1.c1 tried to access method p2.c2.method2()V (p1.c1 is in module m1x of loader myloaders.MySameClassLoader @") ||
+                !message.contains("; p2.c2 is in module m2x of loader myloaders.MySameClassLoader @")) {
+              throw new RuntimeException("Test Failed, an IAE was thrown with the wrong message: " + e.toString());
+            }
+        } catch (Throwable e) {
+            throw new RuntimeException("Test Failed, an IAE should be thrown since p2/c2's method2 is private");
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      ExpQualToM1PrivateMethodIAE test = new ExpQualToM1PrivateMethodIAE();
+      test.createLayerOnBoot();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/modules/AccessCheck/p1/c1.jasm	Mon Jun 25 11:33:11 2018 -0400
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package  p1;
+
+super public class c1 version 55:0 {
+
+    public Method "<init>":"()V"
+    stack 2 locals 2
+    {
+        aload_0;
+        invokespecial Method java/lang/Object."<init>":"()V";
+        new class p2/c2;
+        dup;
+        invokespecial Method p2/c2."<init>":"()V";
+        astore_1;
+        aload_1;
+        invokevirtual Method p2/c2.method2:"()V";
+        return;
+    }
+} // end Class c1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/modules/AccessCheck/p2/c2.jasm	Mon Jun 25 11:33:11 2018 -0400
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package  p2;
+
+super public class c2 version 55:0 {
+    public Method "<init>":"()V"
+    stack 1 locals 1
+    {
+        aload_0;
+        invokespecial Method java/lang/Object."<init>":"()V";
+        return;
+    }
+
+    private Method method2:"()V"
+    stack 0 locals 1
+    {
+        return;
+    }
+} // end Class c2
--- a/test/hotspot/jtreg/runtime/modules/CCE_module_msg.java	Mon Jun 25 20:36:06 2018 +0530
+++ b/test/hotspot/jtreg/runtime/modules/CCE_module_msg.java	Mon Jun 25 11:33:11 2018 -0400
@@ -48,6 +48,7 @@
     public static void main(String[] args) throws Throwable {
         // Should not display version
         invalidObjectToDerived();
+        invalidOriginalInnerToDerived();
         invalidTimeToDerived();
         invalidHeadersToDerived();
         // Should display version
@@ -66,8 +67,25 @@
             }
             throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
         } catch (ClassCastException cce) {
-            System.out.println(cce.getMessage());
-            if (!cce.getMessage().contains("java.base/java.lang.Object cannot be cast to Derived")) {
+            System.out.println(cce.toString());
+            if (!cce.getMessage().contains("class java.lang.Object cannot be cast to class Derived (java.lang.Object is in module java.base of loader 'bootstrap'; Derived is in unnamed module of loader 'app')")) {
+                throw new RuntimeException("Wrong message: " + cce.getMessage());
+            }
+        }
+    }
+
+    public static void invalidOriginalInnerToDerived() {
+        OriginalInner instance = new OriginalInner();
+        int left = 23;
+        int right = 42;
+        try {
+            for (int i = 0; i < 1; i += 1) {
+                left = ((Derived) (java.lang.Object)instance).method(left, right);
+            }
+            throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
+        } catch (ClassCastException cce) {
+            System.out.println(cce.toString());
+            if (!cce.getMessage().contains("class OriginalInner cannot be cast to class Derived (OriginalInner and Derived are in unnamed module of loader 'app')")) {
                 throw new RuntimeException("Wrong message: " + cce.getMessage());
             }
         }
@@ -84,8 +102,8 @@
             }
             throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
         } catch (ClassCastException cce) {
-            System.out.println(cce.getMessage());
-            if (!cce.getMessage().contains("java.sql/java.sql.Time cannot be cast to Derived")) {
+            System.out.println(cce.toString());
+            if (!cce.getMessage().contains("class java.sql.Time cannot be cast to class Derived (java.sql.Time is in module java.sql of loader 'platform'; Derived is in unnamed module of loader 'app')")) {
                 throw new RuntimeException("Wrong message: " + cce.getMessage());
             }
         }
@@ -102,8 +120,8 @@
             }
             throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
         } catch (ClassCastException cce) {
-            System.out.println(cce.getMessage());
-            if (!cce.getMessage().contains("jdk.httpserver/com.sun.net.httpserver.Headers cannot be cast to Derived")) {
+            System.out.println(cce.toString());
+            if (!cce.getMessage().contains("class com.sun.net.httpserver.Headers cannot be cast to class Derived (com.sun.net.httpserver.Headers is in module jdk.httpserver of loader 'platform'; Derived is in unnamed module of loader 'app')")) {
                 throw new RuntimeException("Wrong message: " + cce.getMessage());
             }
         }
@@ -132,10 +150,9 @@
             throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
         } catch (ClassCastException cce) {
             String exception = cce.getMessage();
-            System.out.println(exception);
-            if (exception.contains("module_two/p2.c2") ||
-                !(exception.contains("module_two@") &&
-                  exception.contains("/p2.c2 cannot be cast to java.base/java.lang.String"))) {
+            System.out.println(cce.toString());
+            if (!exception.contains("class p2.c2 cannot be cast to class java.lang.String (p2.c2 is in module module_two@") ||
+                !exception.contains(" of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')")) {
                 throw new RuntimeException("Wrong message: " + exception);
             }
         }
@@ -160,14 +177,21 @@
             throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
         } catch (ClassCastException cce) {
             String exception = cce.getMessage();
-            System.out.println(exception);
-            if (!exception.contains("MyClassLoader//p4.c4 cannot be cast to java.base/java.lang.String")) {
+            System.out.println(cce.toString());
+            if (!exception.contains("class p4.c4 cannot be cast to class java.lang.String (p4.c4 is in unnamed module of loader 'MyClassLoader' @") ||
+                !exception.contains("; java.lang.String is in module java.base of loader 'bootstrap')")) {
                 throw new RuntimeException("Wrong message: " + exception);
             }
         }
     }
 }
 
+class OriginalInner extends java.lang.Object {
+    public int method(int left, int right) {
+        return right;
+    }
+}
+
 class Derived extends java.lang.Object {
     public int method(int left, int right) {
         return right;
--- a/test/hotspot/jtreg/vmTestbase/jit/t/t113/t113.gold	Mon Jun 25 20:36:06 2018 +0530
+++ b/test/hotspot/jtreg/vmTestbase/jit/t/t113/t113.gold	Mon Jun 25 11:33:11 2018 -0400
@@ -1,2 +1,2 @@
-java.lang.ClassCastException: jit.t.t113.kid1 cannot be cast to jit.t.t113.kid2
+java.lang.ClassCastException: class jit.t.t113.kid1 cannot be cast to class jit.t.t113.kid2 (jit.t.t113.kid1 and jit.t.t113.kid2 are in unnamed module of loader 'app')
         at jit.t.t113.t113.main(t113.java:59)