8159470: Error message for ICCE for MethodHandle constant pool not helpful
Summary: Reworded message and added test.
Reviewed-by: hseigel, gtriantafill, dholmes
--- 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