8204268: Improve some IncompatibleClassChangeError messages
Reviewed-by: stuefe, hseigel
This commit is contained in:
parent
d2f70d7052
commit
731d9b1499
@ -955,7 +955,9 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,
|
|||||||
|
|
||||||
if (!interf->is_interface()) {
|
if (!interf->is_interface()) {
|
||||||
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),
|
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()) {
|
if (InstanceKlass::cast(interf)->has_nonstatic_concrete_methods()) {
|
||||||
|
@ -2641,7 +2641,12 @@ Method* InstanceKlass::method_at_itable(Klass* holder, int index, TRAPS) {
|
|||||||
// If the interface isn't implemented by the receiver class,
|
// If the interface isn't implemented by the receiver class,
|
||||||
// the VM should throw IncompatibleClassChangeError.
|
// the VM should throw IncompatibleClassChangeError.
|
||||||
if (cnt >= nof_interfaces) {
|
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();
|
Klass* ik = ioe->interface_klass();
|
||||||
|
@ -22,7 +22,9 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ICC_B implements ICC_iA {
|
package test;
|
||||||
|
|
||||||
|
class ICC2_B implements ICC2_iA {
|
||||||
|
|
||||||
public Method "<init>":"()V"
|
public Method "<init>":"()V"
|
||||||
stack 1 locals 1
|
stack 1 locals 1
|
||||||
@ -36,7 +38,7 @@ class ICC_B implements ICC_iA {
|
|||||||
stack 2 locals 1
|
stack 2 locals 1
|
||||||
{
|
{
|
||||||
getstatic Field java/lang/System.out:"Ljava/io/PrintStream;";
|
getstatic Field java/lang/System.out:"Ljava/io/PrintStream;";
|
||||||
ldc String "B.a()";
|
ldc String "test.B.a()";
|
||||||
invokevirtual Method java/io/PrintStream.print:"(Ljava/lang/String;)V";
|
invokevirtual Method java/io/PrintStream.print:"(Ljava/lang/String;)V";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -45,7 +47,7 @@ class ICC_B implements ICC_iA {
|
|||||||
stack 2 locals 1
|
stack 2 locals 1
|
||||||
{
|
{
|
||||||
getstatic Field java/lang/System.out:"Ljava/io/PrintStream;";
|
getstatic Field java/lang/System.out:"Ljava/io/PrintStream;";
|
||||||
ldc String "B.b()";
|
ldc String "test.B.b()";
|
||||||
invokevirtual Method java/io/PrintStream.print:"(Ljava/lang/String;)V";
|
invokevirtual Method java/io/PrintStream.print:"(Ljava/lang/String;)V";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
@ -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 {
|
||||||
|
}
|
@ -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 {
|
||||||
|
}
|
@ -22,9 +22,7 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
package test;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ImplementsSomeInterfaces extends AbstractICCE0 {
|
class ImplementsSomeInterfaces extends AbstractICCE0 {
|
||||||
|
|
||||||
@ -32,7 +30,7 @@ class ImplementsSomeInterfaces extends AbstractICCE0 {
|
|||||||
stack 1 locals 1
|
stack 1 locals 1
|
||||||
{
|
{
|
||||||
aload_0;
|
aload_0;
|
||||||
invokespecial Method AbstractICCE0."<init>":"()V";
|
invokespecial Method test/AbstractICCE0."<init>":"()V";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,18 +31,20 @@
|
|||||||
* @build sun.hotspot.WhiteBox
|
* @build sun.hotspot.WhiteBox
|
||||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
|
* @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @compile IncompatibleClassChangeErrorTest.java
|
* @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
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
* -XX:CompileThreshold=1000 -XX:-BackgroundCompilation -XX:-Inline
|
* -XX:CompileThreshold=1000 -XX:-BackgroundCompilation -XX:-Inline
|
||||||
* -XX:CompileCommand=exclude,IncompatibleClassChangeErrorTest::test_iccInt
|
* -XX:CompileCommand=exclude,test.IncompatibleClassChangeErrorTest::test_iccInt
|
||||||
* IncompatibleClassChangeErrorTest
|
* test.IncompatibleClassChangeErrorTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
package test;
|
||||||
|
|
||||||
import sun.hotspot.WhiteBox;
|
import sun.hotspot.WhiteBox;
|
||||||
import compiler.whitebox.CompilerWhiteBoxTest;
|
import compiler.whitebox.CompilerWhiteBoxTest;
|
||||||
import java.lang.reflect.Method;
|
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
|
// First, compile the test by @compile. This results in a legal set
|
||||||
// of classes.
|
// of classes.
|
||||||
// Then, with jasm, generate incompatible classes that overwrite
|
// Then, with jasm, generate incompatible classes that overwrite
|
||||||
@ -56,10 +58,10 @@ public class IncompatibleClassChangeErrorTest {
|
|||||||
private static boolean enableChecks = true;
|
private static boolean enableChecks = true;
|
||||||
|
|
||||||
private static String expectedErrorMessageInterpreted =
|
private static String expectedErrorMessageInterpreted =
|
||||||
"Class ImplementsSomeInterfaces " +
|
"Class test.ImplementsSomeInterfaces " +
|
||||||
"does not implement the requested interface InterfaceICCE1";
|
"does not implement the requested interface test.InterfaceICCE1";
|
||||||
private static String expectedErrorMessageCompiled =
|
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"
|
// old message: "vtable stub"
|
||||||
|
|
||||||
|
|
||||||
@ -93,9 +95,9 @@ public class IncompatibleClassChangeErrorTest {
|
|||||||
|
|
||||||
// Compile
|
// Compile
|
||||||
if (!compile(IncompatibleClassChangeErrorTest.class, "test_icc_compiled_itable_stub") ||
|
if (!compile(IncompatibleClassChangeErrorTest.class, "test_icc_compiled_itable_stub") ||
|
||||||
!compile(ICC_C.class, "b") ||
|
!compile(ICC2_C.class, "b") ||
|
||||||
!compile(ICC_D.class, "b") ||
|
!compile(ICC2_D.class, "b") ||
|
||||||
!compile(ICC_E.class, "b")) {
|
!compile(ICC2_E.class, "b")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,6 +121,9 @@ public class IncompatibleClassChangeErrorTest {
|
|||||||
"but got: " + errorMsg);
|
"but got: " + errorMsg);
|
||||||
throw new RuntimeException("Wrong error message of IncompatibleClassChangeError.");
|
throw new RuntimeException("Wrong error message of IncompatibleClassChangeError.");
|
||||||
}
|
}
|
||||||
|
if (enableChecks) {
|
||||||
|
System.out.println("Test 1 passed with message: " + errorMsg);
|
||||||
|
}
|
||||||
caught_icc = true;
|
caught_icc = true;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new RuntimeException("Caught unexpected exception: " + e);
|
throw new RuntimeException("Caught unexpected exception: " + e);
|
||||||
@ -142,10 +147,10 @@ public class IncompatibleClassChangeErrorTest {
|
|||||||
public static void test_icc_compiled_itable_stub() {
|
public static void test_icc_compiled_itable_stub() {
|
||||||
// Allocated the objects we need and call a valid method.
|
// Allocated the objects we need and call a valid method.
|
||||||
boolean caught_icc = false;
|
boolean caught_icc = false;
|
||||||
ICC_B b = new ICC_B();
|
ICC2_B b = new ICC2_B();
|
||||||
ICC_C c = new ICC_C();
|
ICC2_C c = new ICC2_C();
|
||||||
ICC_D d = new ICC_D();
|
ICC2_D d = new ICC2_D();
|
||||||
ICC_E e = new ICC_E();
|
ICC2_E e = new ICC2_E();
|
||||||
b.a();
|
b.a();
|
||||||
c.a();
|
c.a();
|
||||||
d.a();
|
d.a();
|
||||||
@ -155,7 +160,7 @@ public class IncompatibleClassChangeErrorTest {
|
|||||||
final int iterations = 10;
|
final int iterations = 10;
|
||||||
// Test: calls b.b() in the last iteration.
|
// Test: calls b.b() in the last iteration.
|
||||||
for (int i = 0; i < iterations; i++) {
|
for (int i = 0; i < iterations; i++) {
|
||||||
ICC_iB a = b;
|
ICC2_iB a = b;
|
||||||
if (i % 3 == 0 && i < iterations - 1) {
|
if (i % 3 == 0 && i < iterations - 1) {
|
||||||
a = c;
|
a = c;
|
||||||
}
|
}
|
||||||
@ -194,7 +199,7 @@ public class IncompatibleClassChangeErrorTest {
|
|||||||
throw new RuntimeException("Wrong error message of IncompatibleClassChangeError.");
|
throw new RuntimeException("Wrong error message of IncompatibleClassChangeError.");
|
||||||
}
|
}
|
||||||
if (enableChecks) {
|
if (enableChecks) {
|
||||||
System.out.println("Passed with message: " + errorMsg);
|
System.out.println("Test 2 passed with message: " + errorMsg);
|
||||||
}
|
}
|
||||||
} catch (Throwable exc) {
|
} catch (Throwable exc) {
|
||||||
throw exc; // new RuntimeException("Caught unexpected exception: " + exc);
|
throw exc; // new RuntimeException("Caught unexpected exception: " + exc);
|
||||||
@ -206,12 +211,54 @@ public class IncompatibleClassChangeErrorTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
public static void main(String[] args) throws Exception {
|
||||||
if (!setup_test()) {
|
if (!setup_test()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
test_iccInt();
|
test_iccInt();
|
||||||
test_icc_compiled_itable_stub();
|
test_icc_compiled_itable_stub();
|
||||||
|
test3_implementsClass();
|
||||||
|
test4_extendsInterface();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,20 +352,20 @@ class ImplementsSomeInterfaces extends
|
|||||||
// C D E \
|
// C D E \
|
||||||
// B (bad class, missing interface implementation)
|
// B (bad class, missing interface implementation)
|
||||||
|
|
||||||
interface ICC_iA {
|
interface ICC2_iA {
|
||||||
public void a();
|
public void a();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ICC_iB {
|
interface ICC2_iB {
|
||||||
public void b();
|
public void b();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the errorneous class. A variant of it not
|
// This is the erroneous class. A variant of it not
|
||||||
// implementing ICC_iB is copied into the test before
|
// implementing ICC2_iB is copied into the test before
|
||||||
// it is run.
|
// it is run.
|
||||||
class ICC_B implements ICC_iA,
|
class ICC2_B implements ICC2_iA,
|
||||||
// This interface is missing in the .jasm implementation.
|
// This interface is missing in the .jasm implementation.
|
||||||
ICC_iB {
|
ICC2_iB {
|
||||||
public void a() {
|
public void a() {
|
||||||
System.out.print("B.a() ");
|
System.out.print("B.a() ");
|
||||||
}
|
}
|
||||||
@ -328,7 +375,7 @@ class ICC_B implements ICC_iA,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ICC_C implements ICC_iA, ICC_iB {
|
class ICC2_C implements ICC2_iA, ICC2_iB {
|
||||||
public void a() {
|
public void a() {
|
||||||
System.out.print("C.a() ");
|
System.out.print("C.a() ");
|
||||||
}
|
}
|
||||||
@ -338,7 +385,7 @@ class ICC_C implements ICC_iA, ICC_iB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ICC_D implements ICC_iA, ICC_iB {
|
class ICC2_D implements ICC2_iA, ICC2_iB {
|
||||||
public void a() {
|
public void a() {
|
||||||
System.out.print("D.a() ");
|
System.out.print("D.a() ");
|
||||||
}
|
}
|
||||||
@ -348,7 +395,7 @@ class ICC_D implements ICC_iA, ICC_iB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ICC_E implements ICC_iA, ICC_iB {
|
class ICC2_E implements ICC2_iA, ICC2_iB {
|
||||||
public void a() {
|
public void a() {
|
||||||
System.out.print("E.a() ");
|
System.out.print("E.a() ");
|
||||||
}
|
}
|
||||||
@ -357,3 +404,31 @@ class ICC_E implements ICC_iA, ICC_iB {
|
|||||||
System.out.print("E.b() ");
|
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 {
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user