8204268: Improve some IncompatibleClassChangeError messages.
authorgoetz
Fri, 15 Jun 2018 12:31:28 +0200
changeset 50633 b8055b38b252
parent 50632 fd430e352427
child 50634 c349d409262a
8204268: Improve some IncompatibleClassChangeError messages. Reviewed-by: stuefe, hseigel
src/hotspot/share/classfile/classFileParser.cpp
src/hotspot/share/oops/instanceKlass.cpp
test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/ICC2_B.jasm
test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/ICC3_B.jasm
test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/ICC4_B.jasm
test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/ICC_B.jasm
test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/ImplementsSomeInterfaces.jasm
test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/IncompatibleClassChangeErrorTest.java
--- a/src/hotspot/share/classfile/classFileParser.cpp	Tue Jun 19 12:25:42 2018 +0200
+++ b/src/hotspot/share/classfile/classFileParser.cpp	Fri Jun 15 12:31:28 2018 +0200
@@ -955,7 +955,9 @@
 
       if (!interf->is_interface()) {
         THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),
-                   "Implementing class");
+                  err_msg("Class %s can not implement %s, because it is not an interface",
+                          _class_name->as_klass_external_name(),
+                          interf->class_loader_and_module_name()));
       }
 
       if (InstanceKlass::cast(interf)->has_nonstatic_concrete_methods()) {
--- a/src/hotspot/share/oops/instanceKlass.cpp	Tue Jun 19 12:25:42 2018 +0200
+++ b/src/hotspot/share/oops/instanceKlass.cpp	Fri Jun 15 12:31:28 2018 +0200
@@ -2641,7 +2641,12 @@
     // If the interface isn't implemented by the receiver class,
     // the VM should throw IncompatibleClassChangeError.
     if (cnt >= nof_interfaces) {
-      THROW_NULL(vmSymbols::java_lang_IncompatibleClassChangeError());
+      ResourceMark rm(THREAD);
+      stringStream ss;
+      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());
+      THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
     }
 
     Klass* ik = ioe->interface_klass();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/ICC2_B.jasm	Fri Jun 15 12:31:28 2018 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 SAP SE. 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.
+ *
+ * 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 test;
+
+class ICC2_B implements ICC2_iA {
+
+    public Method "<init>":"()V"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokespecial Method java/lang/Object."<init>":"()V";
+        return;
+    }
+
+  public Method a:"()V"
+        stack 2 locals 1
+    {
+        getstatic     Field java/lang/System.out:"Ljava/io/PrintStream;";
+        ldc           String "test.B.a()";
+        invokevirtual Method java/io/PrintStream.print:"(Ljava/lang/String;)V";
+        return;
+    }
+
+  public Method b:"()V"
+        stack 2 locals 1
+    {
+        getstatic     Field java/lang/System.out:"Ljava/io/PrintStream;";
+        ldc           String "test.B.b()";
+        invokevirtual Method java/io/PrintStream.print:"(Ljava/lang/String;)V";
+        return;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/ICC3_B.jasm	Fri Jun 15 12:31:28 2018 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 SAP SE. 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.
+ *
+ * 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 test;
+
+// Erroneous class: ICC3_A is not an interface but a class.
+class ICC3_B implements ICC3_A {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/ICC4_B.jasm	Fri Jun 15 12:31:28 2018 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 SAP SE. 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.
+ *
+ * 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 test;
+
+// Erroneous class: ICC3_iA is not a class but an interface.
+class ICC4_B extends ICC4_iA {
+}
--- a/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/ICC_B.jasm	Tue Jun 19 12:25:42 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2018 SAP SE. 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.
- *
- * 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.
- */
-
-class ICC_B implements ICC_iA {
-
-    public Method "<init>":"()V"
-        stack 1 locals 1
-    {
-        aload_0;
-        invokespecial Method java/lang/Object."<init>":"()V";
-        return;
-    }
-
-  public Method a:"()V"
-        stack 2 locals 1
-    {
-        getstatic     Field java/lang/System.out:"Ljava/io/PrintStream;";
-        ldc           String "B.a()";
-        invokevirtual Method java/io/PrintStream.print:"(Ljava/lang/String;)V";
-        return;
-    }
-
-  public Method b:"()V"
-        stack 2 locals 1
-    {
-        getstatic     Field java/lang/System.out:"Ljava/io/PrintStream;";
-        ldc           String "B.b()";
-        invokevirtual Method java/io/PrintStream.print:"(Ljava/lang/String;)V";
-        return;
-    }
-}
--- a/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/ImplementsSomeInterfaces.jasm	Tue Jun 19 12:25:42 2018 +0200
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/ImplementsSomeInterfaces.jasm	Fri Jun 15 12:31:28 2018 +0200
@@ -22,9 +22,7 @@
  * questions.
  */
 
-
-
-
+package test;
 
 class ImplementsSomeInterfaces extends AbstractICCE0 {
 
@@ -32,7 +30,7 @@
         stack 1 locals 1
     {
         aload_0;
-        invokespecial Method AbstractICCE0."<init>":"()V";
+        invokespecial Method test/AbstractICCE0."<init>":"()V";
         return;
     }
 
--- a/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/IncompatibleClassChangeErrorTest.java	Tue Jun 19 12:25:42 2018 +0200
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/IncompatibleClassChangeErrorTest.java	Fri Jun 15 12:31:28 2018 +0200
@@ -31,18 +31,20 @@
  * @build sun.hotspot.WhiteBox
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
  * @compile IncompatibleClassChangeErrorTest.java
- * @compile ImplementsSomeInterfaces.jasm ICC_B.jasm
+ * @compile ImplementsSomeInterfaces.jasm ICC2_B.jasm ICC3_B.jasm ICC4_B.jasm
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   -XX:CompileThreshold=1000 -XX:-BackgroundCompilation -XX:-Inline
- *                   -XX:CompileCommand=exclude,IncompatibleClassChangeErrorTest::test_iccInt
- *                   IncompatibleClassChangeErrorTest
+ *                   -XX:CompileCommand=exclude,test.IncompatibleClassChangeErrorTest::test_iccInt
+ *                   test.IncompatibleClassChangeErrorTest
  */
 
+package test;
+
 import sun.hotspot.WhiteBox;
 import compiler.whitebox.CompilerWhiteBoxTest;
 import java.lang.reflect.Method;
 
-// This test assembles an errorneous installation of classes.
+// This test assembles an erroneous installation of classes.
 // First, compile the test by @compile. This results in a legal set
 // of classes.
 // Then, with jasm, generate incompatible classes that overwrite
@@ -56,10 +58,10 @@
     private static boolean enableChecks = true;
 
     private static String expectedErrorMessageInterpreted =
-        "Class ImplementsSomeInterfaces " +
-        "does not implement the requested interface InterfaceICCE1";
+        "Class test.ImplementsSomeInterfaces " +
+        "does not implement the requested interface test.InterfaceICCE1";
     private static String expectedErrorMessageCompiled =
-        "Class ICC_B does not implement the requested interface ICC_iB";
+        "Class test.ICC2_B does not implement the requested interface test.ICC2_iB";
         // old message: "vtable stub"
 
 
@@ -93,9 +95,9 @@
 
         // Compile
         if (!compile(IncompatibleClassChangeErrorTest.class, "test_icc_compiled_itable_stub") ||
-            !compile(ICC_C.class, "b") ||
-            !compile(ICC_D.class, "b") ||
-            !compile(ICC_E.class, "b")) {
+            !compile(ICC2_C.class, "b") ||
+            !compile(ICC2_D.class, "b") ||
+            !compile(ICC2_E.class, "b")) {
           return false;
         }
 
@@ -119,6 +121,9 @@
                                    "but got:  " + errorMsg);
                 throw new RuntimeException("Wrong error message of IncompatibleClassChangeError.");
             }
+            if (enableChecks) {
+                System.out.println("Test 1 passed with message: " + errorMsg);
+            }
             caught_icc = true;
         } catch (Throwable e) {
             throw new RuntimeException("Caught unexpected exception: " + e);
@@ -142,10 +147,10 @@
     public static void test_icc_compiled_itable_stub() {
         // Allocated the objects we need and call a valid method.
         boolean caught_icc = false;
-        ICC_B b = new ICC_B();
-        ICC_C c = new ICC_C();
-        ICC_D d = new ICC_D();
-        ICC_E e = new ICC_E();
+        ICC2_B b = new ICC2_B();
+        ICC2_C c = new ICC2_C();
+        ICC2_D d = new ICC2_D();
+        ICC2_E e = new ICC2_E();
         b.a();
         c.a();
         d.a();
@@ -155,7 +160,7 @@
             final int iterations = 10;
             // Test: calls b.b() in the last iteration.
             for (int i = 0; i < iterations; i++) {
-                ICC_iB a = b;
+                ICC2_iB a = b;
                 if (i % 3 == 0 && i < iterations - 1) {
                     a = c;
                 }
@@ -194,7 +199,7 @@
                 throw new RuntimeException("Wrong error message of IncompatibleClassChangeError.");
             }
             if (enableChecks) {
-                System.out.println("Passed with message: " + errorMsg);
+                System.out.println("Test 2 passed with message: " + errorMsg);
             }
         } catch (Throwable exc) {
             throw exc; // new RuntimeException("Caught unexpected exception: " + exc);
@@ -206,12 +211,54 @@
         }
     }
 
+    private static String expectedErrorMessage3 =
+        "Class test.ICC3_B can not implement test.ICC3_A, because it is not an interface";
+
+    public static void test3_implementsClass() throws Exception {
+        try {
+            new ICC3_B();
+            throw new RuntimeException("Expected IncompatibleClassChangeError was not thrown.");
+        } catch (IncompatibleClassChangeError e) {
+            String errorMsg = e.getMessage();
+            if (!errorMsg.equals(expectedErrorMessage3)) {
+                System.out.println("Expected: " + expectedErrorMessage3 + "\n" +
+                                   "but got:  " + errorMsg);
+                throw new RuntimeException("Wrong error message of IncompatibleClassChangeError.");
+            }
+            System.out.println("Test 3 passed with message: " + errorMsg);
+        } catch (Throwable e) {
+            throw new RuntimeException("Caught unexpected exception: " + e);
+        }
+    }
+
+    private static String expectedErrorMessage4 =
+        "class test.ICC4_B has interface test.ICC4_iA as super class";
+
+    public static void test4_extendsInterface() throws Exception {
+        try {
+            new ICC4_B();
+            throw new RuntimeException("Expected IncompatibleClassChangeError was not thrown.");
+        } catch (IncompatibleClassChangeError e) {
+            String errorMsg = e.getMessage();
+            if (!errorMsg.equals(expectedErrorMessage4)) {
+                System.out.println("Expected: " + expectedErrorMessage4 + "\n" +
+                                   "but got:  " + errorMsg);
+                throw new RuntimeException("Wrong error message of IncompatibleClassChangeError.");
+            }
+            System.out.println("Test 4 passed with message: " + errorMsg);
+        } catch (Throwable e) {
+            throw new RuntimeException("Caught unexpected exception: " + e);
+        }
+    }
+
     public static void main(String[] args) throws Exception {
         if (!setup_test()) {
             return;
         }
         test_iccInt();
         test_icc_compiled_itable_stub();
+        test3_implementsClass();
+        test4_extendsInterface();
     }
 }
 
@@ -305,20 +352,20 @@
 //         C D E \
 //                B (bad class, missing interface implementation)
 
-interface ICC_iA {
+interface ICC2_iA {
     public void a();
 }
 
-interface ICC_iB {
+interface ICC2_iB {
     public void b();
 }
 
-// This is the errorneous class. A variant of it not
-// implementing ICC_iB is copied into the test before
+// This is the erroneous class. A variant of it not
+// implementing ICC2_iB is copied into the test before
 // it is run.
-class ICC_B implements ICC_iA,
+class ICC2_B implements ICC2_iA,
                        // This interface is missing in the .jasm implementation.
-                       ICC_iB {
+                       ICC2_iB {
     public void a() {
         System.out.print("B.a() ");
     }
@@ -328,7 +375,7 @@
     }
 }
 
-class ICC_C implements ICC_iA, ICC_iB {
+class ICC2_C implements ICC2_iA, ICC2_iB {
     public void a() {
         System.out.print("C.a() ");
     }
@@ -338,7 +385,7 @@
     }
 }
 
-class ICC_D implements ICC_iA, ICC_iB {
+class ICC2_D implements ICC2_iA, ICC2_iB {
     public void a() {
         System.out.print("D.a() ");
     }
@@ -348,7 +395,7 @@
     }
 }
 
-class ICC_E implements ICC_iA, ICC_iB {
+class ICC2_E implements ICC2_iA, ICC2_iB {
     public void a() {
         System.out.print("E.a() ");
     }
@@ -357,3 +404,31 @@
         System.out.print("E.b() ");
     }
 }
+
+// Helper classes to test error where class appears in implements statement.
+//
+// Class hierachy:
+//
+//       A  Some Class.
+//       |
+//       B  erroneous class. Correct B extends A, incorrect B (from jasm) implements A.
+
+class ICC3_A {
+}
+
+class ICC3_B extends ICC3_A {
+}
+
+// Helper classes to test error where interface appears in extends statement.
+//
+// Class hierachy:
+//
+//       A  Some Interface.
+//       |
+//       B  erroneous class. Correct B implements A, incorrect B (from jasm) extends A.
+
+interface ICC4_iA {
+}
+
+class ICC4_B implements ICC4_iA {
+}