8159470: Error message for ICCE for MethodHandle constant pool not helpful
authorcoleenp
Mon, 20 Jun 2016 12:28:14 -0400
changeset 39398 16b3ed4012f8
parent 39396 84aae7f2f638
child 39399 9f8d0683c90f
8159470: Error message for ICCE for MethodHandle constant pool not helpful Summary: Reworded message and added test. Reviewed-by: hseigel, gtriantafill, dholmes
hotspot/src/share/vm/oops/constantPool.cpp
hotspot/test/runtime/ConstantPool/TestMethodHandleConstant.java
hotspot/test/runtime/ConstantPool/WithConfiguration.jcod
--- a/hotspot/src/share/vm/oops/constantPool.cpp	Mon Jun 13 13:52:38 2016 +0200
+++ b/hotspot/src/share/vm/oops/constantPool.cpp	Mon Jun 20 12:28:14 2016 -0400
@@ -691,16 +691,21 @@
                               ref_kind, index, this_cp->method_handle_index_at(index),
                               callee_index, name->as_C_string(), signature->as_C_string());
       }
-      KlassHandle callee;
-      { Klass* k = klass_at_impl(this_cp, callee_index, true, CHECK_NULL);
-        callee = KlassHandle(THREAD, k);
-      }
+
+      Klass* k = klass_at_impl(this_cp, callee_index, true, CHECK_NULL);
+      KlassHandle callee(THREAD, k);
+
+      // Check constant pool method consistency
       if ((callee->is_interface() && m_tag.is_method()) ||
-          (!callee->is_interface() && m_tag.is_interface_method())) {
+          ((!callee->is_interface() && m_tag.is_interface_method()))) {
         ResourceMark rm(THREAD);
-        char buf[200];
-        jio_snprintf(buf, sizeof(buf), "Inconsistent constant data for %s.%s%s at index %d",
-          callee->name()->as_C_string(), name->as_C_string(), signature->as_C_string(), index);
+        char buf[400];
+        jio_snprintf(buf, sizeof(buf),
+          "Inconsistent constant pool data in classfile for class %s. "
+          "Method %s%s at index %d is %s and should be %s",
+          callee->name()->as_C_string(), name->as_C_string(), signature->as_C_string(), index,
+          callee->is_interface() ? "CONSTANT_MethodRef" : "CONSTANT_InterfaceMethodRef",
+          callee->is_interface() ? "CONSTANT_InterfaceMethodRef" : "CONSTANT_MethodRef");
         THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
       }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/ConstantPool/TestMethodHandleConstant.java	Mon Jun 20 12:28:14 2016 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * 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
+ * @bug 8159470
+ * @summary Test that MethodHandle constants are checked
+ * @modules java.base/jdk.internal.misc
+ * @compile WithConfiguration.jcod
+ * @run main/othervm TestMethodHandleConstant
+ */
+public class TestMethodHandleConstant {
+
+    public static void main(String[] args) {
+        try {
+          // This interface has bad constant pool entry for MethodHandle -> Method
+          String URI_DEFAULT
+            = WithConfiguration.autoDetect().getLocation();
+          throw new RuntimeException("FAILED, ICCE not thrown");
+        } catch (BootstrapMethodError icce) {
+          System.out.println("PASSED, expecting ICCE" + icce.getMessage());
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/ConstantPool/WithConfiguration.jcod	Mon Jun 20 12:28:14 2016 -0400
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * 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.
+ */
+
+// This class has a MethodHandle constant that points to an incompatible Methodref constant
+// (should be InterfaceMethodref)
+// Throws ICCE/BootstrapMethodError
+
+// public interface WithConfiguration {
+//     String getLocation();
+//     static WithConfiguration autoDetect() {
+//         return () -> "$Default$";
+//     }
+// }
+
+class WithConfiguration {
+  0xCAFEBABE;
+  0; // minor version
+  53; // version
+  [] { // Constant Pool
+    ; // first element is empty
+    InvokeDynamic 0s #18; // #1    
+    String #19; // #2    
+    class #20; // #3    
+    class #21; // #4    
+    Utf8 "getLocation"; // #5    
+    Utf8 "()Ljava/lang/String;"; // #6    
+    Utf8 "autoDetect"; // #7    
+    Utf8 "()LWithConfiguration;"; // #8    
+    Utf8 "Code"; // #9    
+    Utf8 "LineNumberTable"; // #10    
+    Utf8 "lambda$autoDetect$0"; // #11    
+    Utf8 "SourceFile"; // #12    
+    Utf8 "WithConfiguration.java"; // #13    
+    Utf8 "BootstrapMethods"; // #14    
+    MethodHandle 6b #22; // #15    
+    MethodType #6; // #16    
+    MethodHandle 6b #23; // #17    
+    NameAndType #5 #8; // #18    
+    Utf8 "$Default$"; // #19    
+    Utf8 "WithConfiguration"; // #20    
+    Utf8 "java/lang/Object"; // #21    
+    Method #24 #25; // #22    
+    Method #3 #26; // #23      THIS IS WRONG!!
+    class #27; // #24    
+    NameAndType #28 #32; // #25    
+    NameAndType #11 #6; // #26    
+    Utf8 "java/lang/invoke/LambdaMetafactory"; // #27    
+    Utf8 "metafactory"; // #28    
+    class #34; // #29    
+    Utf8 "Lookup"; // #30    
+    Utf8 "InnerClasses"; // #31    
+    Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"; // #32    
+    class #35; // #33    
+    Utf8 "java/lang/invoke/MethodHandles$Lookup"; // #34    
+    Utf8 "java/lang/invoke/MethodHandles"; // #35    
+  } // Constant Pool
+
+  0x0601; // access
+  #3;// this_cpx
+  #4;// super_cpx
+
+  [] { // Interfaces
+  } // Interfaces
+
+  [] { // fields
+  } // fields
+
+  [] { // methods
+    { // Member
+      0x0401; // access
+      #5; // name_cpx
+      #6; // sig_cpx
+      [] { // Attributes
+      } // Attributes
+    } // Member
+    ;
+    { // Member
+      0x0009; // access
+      #7; // name_cpx
+      #8; // sig_cpx
+      [] { // Attributes
+        Attr(#9) { // Code
+          1; // max_stack
+          0; // max_locals
+          Bytes[]{
+            0xBA00010000B0;
+          };
+          [] { // Traps
+          } // end Traps
+          [] { // Attributes
+            Attr(#10) { // LineNumberTable
+              [] { // LineNumberTable
+                0  26;
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+    ;
+    { // Member
+      0x100A; // access
+      #11; // name_cpx
+      #6; // sig_cpx
+      [] { // Attributes
+        Attr(#9) { // Code
+          1; // max_stack
+          0; // max_locals
+          Bytes[]{
+            0x1202B0;
+          };
+          [] { // Traps
+          } // end Traps
+          [] { // Attributes
+            Attr(#10) { // LineNumberTable
+              [] { // LineNumberTable
+                0  26;
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+  } // methods
+
+  [] { // Attributes
+    Attr(#12) { // SourceFile
+      #13;
+    } // end SourceFile
+    ;
+    Attr(#31) { // InnerClasses
+      [] { // InnerClasses
+        #29 #33 #30 25;
+      }
+    } // end InnerClasses
+    ;
+    Attr(#14) { // BootstrapMethods
+      [] { // bootstrap_methods
+        {  //  bootstrap_method
+          #15; // bootstrap_method_ref
+          [] { // bootstrap_arguments
+            #16;
+            #17;
+            #16;
+          }  //  bootstrap_arguments
+        }  //  bootstrap_method
+      }
+    } // end BootstrapMethods
+  } // Attributes
+} // end class WithConfiguration