8202913: loader constraint message for fields specifies incorrect referring class
Improve the message to display the right referring class. Reviewed-by: acorn, goetz, dholmes
This commit is contained in:
parent
fcb805f9a6
commit
d892ac8d4c
@ -688,19 +688,21 @@ void LinkResolver::check_field_loader_constraints(Symbol* field, Symbol* sig,
|
|||||||
CHECK);
|
CHECK);
|
||||||
if (failed_type_symbol != NULL) {
|
if (failed_type_symbol != NULL) {
|
||||||
const char* msg = "loader constraint violation: when resolving field"
|
const char* msg = "loader constraint violation: when resolving field"
|
||||||
" \"%s\" the class loader %s of the referring class, "
|
" \"%s\" of type %s, the class loader %s of the current class, "
|
||||||
"%s, and the class loader %s for the field's resolved "
|
"%s, and the class loader %s for the field's defining "
|
||||||
"type, %s, have different Class objects for that type";
|
"type, %s, have different Class objects for type %s";
|
||||||
char* field_name = field->as_C_string();
|
const char* field_name = field->as_C_string();
|
||||||
const char* loader1_name = java_lang_ClassLoader::describe_external(ref_loader());
|
const char* loader1_name = java_lang_ClassLoader::describe_external(ref_loader());
|
||||||
char* sel = sel_klass->name()->as_C_string();
|
const char* sel = sel_klass->external_name();
|
||||||
const char* loader2_name = java_lang_ClassLoader::describe_external(sel_loader());
|
const char* loader2_name = java_lang_ClassLoader::describe_external(sel_loader());
|
||||||
char* failed_type_name = failed_type_symbol->as_C_string();
|
const char* failed_type_name = failed_type_symbol->as_klass_external_name();
|
||||||
size_t buflen = strlen(msg) + strlen(field_name) + strlen(loader1_name) +
|
const char* curr_klass_name = current_klass->external_name();
|
||||||
strlen(sel) + strlen(loader2_name) + strlen(failed_type_name) + 1;
|
size_t buflen = strlen(msg) + strlen(field_name) + 2 * strlen(failed_type_name) +
|
||||||
|
strlen(loader1_name) + strlen(curr_klass_name) +
|
||||||
|
strlen(loader2_name) + strlen(sel) + 1;
|
||||||
char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
|
char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
|
||||||
jio_snprintf(buf, buflen, msg, field_name, loader1_name, sel, loader2_name,
|
jio_snprintf(buf, buflen, msg, field_name, failed_type_name, loader1_name,
|
||||||
failed_type_name);
|
curr_klass_name, loader2_name, sel, failed_type_name);
|
||||||
THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
|
THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* @compile pkg/Grand.java pkg/Parent.java pkg/ClassLoaderForParentFoo.java
|
||||||
|
* @compile pkg/ClassLoaderForChildGrandFoo.java pkg/Child.jasm
|
||||||
|
* @run main/othervm LdrCnstrFldMsgTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
// Check that LinkageError loader constraint message for fields contains the
|
||||||
|
// correct information.
|
||||||
|
//
|
||||||
|
// The test creates two class loaders. The first class loader loads classes
|
||||||
|
// Child, Foo, and Grand. The second class loader loads Parent and Foo. Class
|
||||||
|
// Parent is a sub-class of Grand and class Child is a sub-class of Parent.
|
||||||
|
// Class Child tries to load Parent._field1. This should fail because type Foo
|
||||||
|
// for Parent._field1 is a different type than Child's Foo.
|
||||||
|
//
|
||||||
|
public class LdrCnstrFldMsgTest {
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
ClassLoader l = new pkg.ClassLoaderForChildGrandFoo("pkg.Foo", "pkg.Child", "pkg.Grand");
|
||||||
|
l.loadClass("pkg.Foo");
|
||||||
|
|
||||||
|
// Try to call a public method in Grand.
|
||||||
|
Runnable r = (Runnable) l.loadClass("pkg.Child").newInstance();
|
||||||
|
try {
|
||||||
|
r.run();
|
||||||
|
throw new RuntimeException("Expected LinkageError exception not thrown");
|
||||||
|
} catch (java.lang.LinkageError e) {
|
||||||
|
if (!e.getMessage().contains("for the field's defining type, pkg.Parent,") ||
|
||||||
|
!e.getMessage().contains("have different Class objects for type pkg.Foo")) {
|
||||||
|
throw new RuntimeException("Wrong LinkageError exception thrown: " + e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 pkg;
|
||||||
|
|
||||||
|
// The getfield of Parent._field1 gets a LinkageError because class Parent
|
||||||
|
// has a different Foo class than Child, causing a loader constraint violation.
|
||||||
|
super public class Child extends pkg/Parent implements java/lang/Runnable version 50:0 {
|
||||||
|
|
||||||
|
public Method "<init>":"()V" stack 1 locals 1 {
|
||||||
|
aload_0;
|
||||||
|
invokespecial Method pkg/Parent."<init>":"()V";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Method run:"()V" stack 4 locals 4 {
|
||||||
|
ldc class pkg/Foo;
|
||||||
|
astore_1;
|
||||||
|
new class pkg/Child;
|
||||||
|
dup;
|
||||||
|
invokespecial Method pkg/Child."<init>":"()V";
|
||||||
|
astore_2;
|
||||||
|
aload_2;
|
||||||
|
getstatic Field pkg/Parent._field1:"Lpkg/Foo;";
|
||||||
|
pop;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end Class Child
|
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 pkg;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
// This class loader loads Foo, Child, and Grand.
|
||||||
|
public class ClassLoaderForChildGrandFoo extends ClassLoader {
|
||||||
|
|
||||||
|
ClassLoader l2 = null;
|
||||||
|
|
||||||
|
private final Set<String> names = new HashSet<>();
|
||||||
|
|
||||||
|
public ClassLoaderForChildGrandFoo(String... names) {
|
||||||
|
for (String n : names) this.names.add(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||||
|
// Create class loader l2 to load Parent and Foo. And, pass this class
|
||||||
|
// loader to l2 so l2 can use it to load Grand.
|
||||||
|
if (name.contains("Parent") && l2 == null) {
|
||||||
|
l2 = new ClassLoaderForParentFoo(this, "pkg.Foo", "pkg.Grand", "pkg.Parent");
|
||||||
|
Class<?> b = l2.loadClass("pkg.Parent");
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
if (!names.contains(name)) return super.loadClass(name, resolve);
|
||||||
|
Class<?> result = findLoadedClass(name);
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
String filename = name.replace('.', '/') + ".class";
|
||||||
|
try (InputStream data = getResourceAsStream(filename)) {
|
||||||
|
if (data == null) throw new ClassNotFoundException();
|
||||||
|
try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) {
|
||||||
|
int b;
|
||||||
|
do {
|
||||||
|
b = data.read();
|
||||||
|
if (b >= 0) buffer.write(b);
|
||||||
|
} while (b >= 0);
|
||||||
|
byte[] bytes = buffer.toByteArray();
|
||||||
|
result = defineClass(name, bytes, 0, bytes.length);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ClassNotFoundException("Error reading class file", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resolve) resolveClass(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 pkg;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
// This class loader loads Foo and Parent and calls back to l1 to load Grand.
|
||||||
|
public class ClassLoaderForParentFoo extends ClassLoader {
|
||||||
|
|
||||||
|
private final Set<String> names = new HashSet<>();
|
||||||
|
|
||||||
|
ClassLoader l1;
|
||||||
|
|
||||||
|
public ClassLoaderForParentFoo(ClassLoader l, String... names) {
|
||||||
|
l1 = l;
|
||||||
|
for (String n : names) this.names.add(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||||
|
if (name.contains("Grand")) return l1.loadClass("pkg.Grand");
|
||||||
|
if (!names.contains(name)) return super.loadClass(name, resolve);
|
||||||
|
Class<?> result = findLoadedClass(name);
|
||||||
|
if (result == null) {
|
||||||
|
// Load our own version of Foo that will be referenced by Parent.
|
||||||
|
if (name.contains("Parent")) loadClass("pkg.Foo", resolve);
|
||||||
|
String filename = name.replace('.', '/') + ".class";
|
||||||
|
try (InputStream data = getResourceAsStream(filename)) {
|
||||||
|
if (data == null) throw new ClassNotFoundException();
|
||||||
|
try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) {
|
||||||
|
int b;
|
||||||
|
do {
|
||||||
|
b = data.read();
|
||||||
|
if (b >= 0) buffer.write(b);
|
||||||
|
} while (b >= 0);
|
||||||
|
byte[] bytes = buffer.toByteArray();
|
||||||
|
result = defineClass(name, bytes, 0, bytes.length);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ClassNotFoundException("Error reading class file", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resolve) resolveClass(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 pkg;
|
||||||
|
|
||||||
|
public class Foo {}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 pkg;
|
||||||
|
|
||||||
|
public class Grand {
|
||||||
|
public static Foo _field1;
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 pkg;
|
||||||
|
|
||||||
|
public class Parent extends Grand {
|
||||||
|
public static Foo _field1;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user