Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8298065: Provide more information in message of NoSuchFieldError #11745

Closed
wants to merge 13 commits into from
6 changes: 0 additions & 6 deletions src/hotspot/share/interpreter/linkResolver.cpp
Original file line number Diff line number Diff line change
@@ -983,17 +983,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);
/*stringStream ss;
ss.print("Class %s does not have field '", resolved_klass->external_name());
sig->print_as_signature_external_return_type(&ss);
ss.print(" %s'", field->as_C_string());
THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), ss.as_string());*/
THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(),
err_msg("Class %s does not have field '%s %s'",
resolved_klass->external_name(),
Signature::field_type_string(sig),
field->as_C_string()));
//type2name(Signature::basic_type(sig->char_at(0)))
}

// Access checking may be turned off when calling from within the VM.
25 changes: 13 additions & 12 deletions src/hotspot/share/runtime/signature.cpp
Original file line number Diff line number Diff line change
@@ -436,26 +436,27 @@ Symbol* Signature::strip_envelope(const Symbol* signature) {
}

const char* Signature::field_type_string(const Symbol* signature) {
if (basic_type(signature->char_at(0)) == T_OBJECT) {
return field_type_string_impl(signature, 0);
}

const char* Signature::field_type_string_impl(const Symbol* signature, int index) {
if (basic_type(signature->char_at(index)) == T_OBJECT) {
return strip_envelope(signature)->as_C_string();
} else if (basic_type(signature->char_at(0)) == T_ARRAY) {
char* buf = NEW_RESOURCE_ARRAY(char, 64);
buf[signature->utf8_length()] = '\0';
} else if (basic_type(signature->char_at(index)) == T_ARRAY) {
int i;
// Unravel and count array layers
for (i = 0; i < signature->utf8_length() && signature->char_at(i) == JVM_SIGNATURE_ARRAY; i++);
if (basic_type(signature->char_at(i)) == T_OBJECT) {
strcpy(buf, strip_envelope(signature)->as_C_string());
} else {
strcpy(buf, type2name(Signature::basic_type(signature->char_at(i))));
}
char* buf = NEW_RESOURCE_ARRAY(char, 64);
strncpy(buf, field_type_string_impl(signature, i), 64);
// Append array braces to type name
for (int j = 0; j < i; j++) {
buf[strlen(buf)] = '\0';
strncat(buf, "[]", strlen(buf));
buf[strlen(buf)] = '\0';
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Java array dimensions can be up to 255, so the buf is not long enough.

Anyway, I think we already have code that can translate a signature like [I to the source code form of int []. Try this:

super class Foofoo
	version 63:0
{
  public static Method main:"([Ljava/lang/String;)V"
	stack 30 locals 3
  {
                iconst_0;
                iconst_0;
                aconst_null;
		invokestatic	Method "xxx":"(II[I)V";
		return;
  }
} 

$ java -cp . Foofoo
Exception in thread "main" java.lang.NoSuchMethodError: 'void Foofoo.xxx(int, int, int[])'
	at Foofoo.main(Foofoo.jasm)

Writing such conversion is very difficult. You should try to use the existing code (refactoring it as necessary).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a while of searching I was unable to find anything that could easily provide this type of information. The closest example is Signature::print_as_signature_external_return_type, but this does not work with fields.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore my above comment, I found a way to rework a method in symbol.cpp to accomplish the same task more safely. Thank you for this!

return buf;
} else {
return (char*)type2name(Signature::basic_type(signature->char_at(0)));
}
// If it is a primitive, grab its basic type and return
return (char*)type2name(Signature::basic_type(signature->char_at(index)));
}

static const int jl_len = 10, object_len = 6, jl_object_len = jl_len + object_len;
1 change: 1 addition & 0 deletions src/hotspot/share/runtime/signature.hpp
Original file line number Diff line number Diff line change
@@ -125,6 +125,7 @@ class Signature : AllStatic {
// Symbol's refcount, use TempNewSymbol.
static Symbol* strip_envelope(const Symbol* signature);

static const char* field_type_string_impl(const Symbol* signature, int index);
static const char* field_type_string(const Symbol* signature);

// Assuming it's either a field or method descriptor, determine