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);
|
||||
if (failed_type_symbol != NULL) {
|
||||
const char* msg = "loader constraint violation: when resolving field"
|
||||
" \"%s\" the class loader %s of the referring class, "
|
||||
"%s, and the class loader %s for the field's resolved "
|
||||
"type, %s, have different Class objects for that type";
|
||||
char* field_name = field->as_C_string();
|
||||
" \"%s\" of type %s, the class loader %s of the current class, "
|
||||
"%s, and the class loader %s for the field's defining "
|
||||
"type, %s, have different Class objects for type %s";
|
||||
const char* field_name = field->as_C_string();
|
||||
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());
|
||||
char* failed_type_name = failed_type_symbol->as_C_string();
|
||||
size_t buflen = strlen(msg) + strlen(field_name) + strlen(loader1_name) +
|
||||
strlen(sel) + strlen(loader2_name) + strlen(failed_type_name) + 1;
|
||||
const char* failed_type_name = failed_type_symbol->as_klass_external_name();
|
||||
const char* curr_klass_name = current_klass->external_name();
|
||||
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);
|
||||
jio_snprintf(buf, buflen, msg, field_name, loader1_name, sel, loader2_name,
|
||||
failed_type_name);
|
||||
jio_snprintf(buf, buflen, msg, field_name, failed_type_name, loader1_name,
|
||||
curr_klass_name, loader2_name, sel, failed_type_name);
|
||||
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