8298065: Provide more information in message of NoSuchFieldError
Reviewed-by: dholmes, iklam, coleenp
This commit is contained in:
parent
a17b563f54
commit
43847c43ad
src/hotspot/share
test/hotspot/jtreg/runtime/linkResolver
@ -975,7 +975,11 @@ void LinkResolver::resolve_field(fieldDescriptor& fd,
|
||||
// check if field exists; i.e., if a klass containing the field def has been selected
|
||||
if (sel_klass == NULL) {
|
||||
ResourceMark rm(THREAD);
|
||||
THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
|
||||
stringStream ss;
|
||||
ss.print("Class %s does not have member field '", resolved_klass->external_name());
|
||||
sig->print_as_field_external_type(&ss);
|
||||
ss.print(" %s'", field->as_C_string());
|
||||
THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), ss.as_string());
|
||||
}
|
||||
|
||||
// Access checking may be turned off when calling from within the VM.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2023, 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
|
||||
@ -294,6 +294,25 @@ void Symbol::print_as_signature_external_parameters(outputStream *os) {
|
||||
}
|
||||
}
|
||||
|
||||
void Symbol::print_as_field_external_type(outputStream *os) {
|
||||
SignatureStream ss(this, false);
|
||||
assert(!ss.is_done(), "must have at least one element in field ref");
|
||||
assert(!ss.at_return_type(), "field ref cannot be a return type");
|
||||
assert(!Signature::is_method(this), "field ref cannot be a method");
|
||||
|
||||
if (ss.is_array()) {
|
||||
print_array(os, ss);
|
||||
} else if (ss.is_reference()) {
|
||||
print_class(os, ss);
|
||||
} else {
|
||||
os->print("%s", type2name(ss.type()));
|
||||
}
|
||||
#ifdef ASSERT
|
||||
ss.next();
|
||||
assert(ss.is_done(), "must have at most one element in field ref");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Increment refcount while checking for zero. If the Symbol's refcount becomes zero
|
||||
// a thread could be concurrently removing the Symbol. This is used during SymbolTable
|
||||
// lookup to avoid reviving a dead Symbol.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2023, 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
|
||||
@ -275,6 +275,7 @@ class Symbol : public MetaspaceObj {
|
||||
// separated by ', ' to the outputStream. Prints external names as
|
||||
// 'double' or 'java.lang.Object[][]'.
|
||||
void print_as_signature_external_parameters(outputStream *os);
|
||||
void print_as_field_external_type(outputStream *os);
|
||||
|
||||
void metaspace_pointers_do(MetaspaceClosure* it);
|
||||
MetaspaceObj::Type type() const { return SymbolType; }
|
||||
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
public class NoSuchFieldArray {
|
||||
static char[] z;
|
||||
public NoSuchFieldArray() {
|
||||
z = new char[1];
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
super public class NoSuchFieldArray
|
||||
version 65:0
|
||||
{
|
||||
// REMOVED static Field z:"[C";
|
||||
|
||||
public Method "<init>":"()V"
|
||||
stack 1 locals 1
|
||||
{
|
||||
aload_0;
|
||||
invokespecial Method java/lang/Object."<init>":"()V";
|
||||
iconst_1;
|
||||
newarray char;
|
||||
putstatic Field z:"[C";
|
||||
return;
|
||||
}
|
||||
|
||||
} // end Class NoSuchFieldArray
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
public class NoSuchFieldMultiArray {
|
||||
static double[][] a;
|
||||
public NoSuchFieldMultiArray() {
|
||||
a = new double[1][1];
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
super public class NoSuchFieldMultiArray
|
||||
version 65:0
|
||||
{
|
||||
// REMOVED static Field a:"[[D";
|
||||
|
||||
public Method "<init>":"()V"
|
||||
stack 2 locals 1
|
||||
{
|
||||
aload_0;
|
||||
invokespecial Method java/lang/Object."<init>":"()V";
|
||||
iconst_1;
|
||||
iconst_1;
|
||||
multianewarray class "[[D", 2;
|
||||
putstatic Field a:"[[D";
|
||||
return;
|
||||
}
|
||||
|
||||
} // end Class NoSuchFieldMultiArray
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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 8298065
|
||||
* @summary Test output of NoSuchFieldError when field signature does not match
|
||||
* @compile NoSuchFieldPrimitive.jasm NoSuchFieldReference.jasm TestClass.java
|
||||
* @compile NoSuchFieldArray.jasm NoSuchFieldMultiArray.jasm
|
||||
* @run main NoSuchFieldOutputTest
|
||||
*/
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
// Tests the output text of NoSuchFieldError
|
||||
public class NoSuchFieldOutputTest {
|
||||
|
||||
public static void main(java.lang.String[] unused) throws Exception {
|
||||
try {
|
||||
Class.forName("NoSuchFieldPrimitive").newInstance();
|
||||
} catch (NoSuchFieldError nsfe) {
|
||||
testNoSuchFieldOutput(nsfe, "primitive");
|
||||
}
|
||||
try {
|
||||
Class.forName("NoSuchFieldReference").newInstance();
|
||||
} catch (NoSuchFieldError nsfe) {
|
||||
testNoSuchFieldOutput(nsfe, "reference");
|
||||
}
|
||||
try {
|
||||
Class.forName("NoSuchFieldArray").newInstance();
|
||||
} catch (NoSuchFieldError nsfe) {
|
||||
testNoSuchFieldOutput(nsfe, "array");
|
||||
}
|
||||
try {
|
||||
Class.forName("NoSuchFieldMultiArray").newInstance();
|
||||
} catch (NoSuchFieldError nsfe) {
|
||||
testNoSuchFieldOutput(nsfe, "multiArray");
|
||||
}
|
||||
}
|
||||
|
||||
private static void testNoSuchFieldOutput(NoSuchFieldError nsfe, String testType) throws Exception {
|
||||
Pattern noSuchFieldPattern = Pattern.compile("Class (?<classname>[\\w\\d]+) does not have member field '(?<signature>[\\S]+) (?<varname>[\\w\\d]+)'");
|
||||
String output = nsfe.getMessage();
|
||||
Matcher noSuchFieldMatcher = noSuchFieldPattern.matcher(output);
|
||||
if (noSuchFieldMatcher.matches()) {
|
||||
switch (testType) {
|
||||
case "primitive":
|
||||
checkOutputGroups(noSuchFieldMatcher, output, "NoSuchFieldPrimitive", "int", "x");
|
||||
break;
|
||||
case "reference":
|
||||
checkOutputGroups(noSuchFieldMatcher, output, "NoSuchFieldReference", "TestClass", "y");
|
||||
break;
|
||||
case "array":
|
||||
checkOutputGroups(noSuchFieldMatcher, output, "NoSuchFieldArray", "char[]", "z");
|
||||
break;
|
||||
case "multiArray":
|
||||
checkOutputGroups(noSuchFieldMatcher, output, "NoSuchFieldMultiArray", "double[][]", "a");
|
||||
break;
|
||||
default:
|
||||
throwTestException("No matching test", output);
|
||||
}
|
||||
} else {
|
||||
throwTestException("Output format does not match", output);
|
||||
}
|
||||
System.out.println(output);
|
||||
}
|
||||
|
||||
private static void checkOutputGroups(Matcher noSuchFieldMatcher, String output,
|
||||
String testClass, String testSig, String testVar) throws Exception {
|
||||
String classname = noSuchFieldMatcher.group("classname");
|
||||
String signature = noSuchFieldMatcher.group("signature");
|
||||
String varname = noSuchFieldMatcher.group("varname");
|
||||
if (!classname.equals(testClass)) {
|
||||
throwTestException("Failed to match class name", output);
|
||||
}
|
||||
if (!signature.equals(testSig)) {
|
||||
throwTestException("Failed to match type signature", output);
|
||||
}
|
||||
if (!varname.equals(testVar)) {
|
||||
throwTestException("Failed to match field name", output);
|
||||
}
|
||||
}
|
||||
|
||||
private static void throwTestException(String reason, String output) throws Exception {
|
||||
throw new Exception(reason + " . Stdout is :\n" + output);
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
public class NoSuchFieldPrimitive {
|
||||
// static int x;
|
||||
public NoSuchFieldPrimitive() {
|
||||
x = 123;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
super public class NoSuchFieldPrimitive
|
||||
version 65:0
|
||||
{
|
||||
// REMOVED static Field x:I;
|
||||
|
||||
public Method "<init>":"()V"
|
||||
stack 1 locals 1
|
||||
{
|
||||
aload_0;
|
||||
invokespecial Method java/lang/Object."<init>":"()V";
|
||||
bipush 123;
|
||||
putstatic Field x:"I";
|
||||
return;
|
||||
}
|
||||
|
||||
} // end Class NoSuchFieldPrimitive
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
public class NoSuchFieldReference {
|
||||
static TestClass y;
|
||||
public NoSuchFieldReference() {
|
||||
y = new TestClass();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
super public class NoSuchFieldReference
|
||||
version 65:0
|
||||
{
|
||||
// REMOVED static Field y:"LTestClass;";
|
||||
|
||||
public Method "<init>":"()V"
|
||||
stack 2 locals 1
|
||||
{
|
||||
aload_0;
|
||||
invokespecial Method java/lang/Object."<init>":"()V";
|
||||
new class TestClass;
|
||||
dup;
|
||||
invokespecial Method TestClass."<init>":"()V";
|
||||
putstatic Field y:"LTestClass;";
|
||||
return;
|
||||
}
|
||||
|
||||
} // end Class NoSuchFieldReference
|
25
test/hotspot/jtreg/runtime/linkResolver/TestClass.java
Normal file
25
test/hotspot/jtreg/runtime/linkResolver/TestClass.java
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
// Used as a reference type for a field in NoSuchFieldReference.jasm
|
||||
public class TestClass {}
|
Loading…
x
Reference in New Issue
Block a user