Interpreting java.lang.NoSuchMethodError message
Asked Answered
S

2

76

I get the following runtime error message (along with the first line of the stack trace, which points to line 94). I'm trying to figure out why it says no such method exists.

java.lang.NoSuchMethodError: 
com.sun.tools.doclets.formats.html.SubWriterHolderWriter.printDocLinkForMenu(
    ILcom/sun/javadoc/ClassDoc;Lcom/sun/javadoc/MemberDoc;
    Ljava/lang/String;Z)Ljava/lang/String;
at com.sun.tools.doclets.formats.html.AbstractExecutableMemberWriter.writeSummaryLink(
    AbstractExecutableMemberWriter.java:94)

Line 94 of writeSummaryLink is shown below.

QUESTIONS
What does "ILcom" or "Z" mean?
Why there are four types in parentheses (ILcom/sun/javadoc/ClassDoc;Lcom/sun/javadoc/MemberDoc;Ljava/lang/String;Z) and one after the parentheses Ljava/lang/String; when the method printDocLinkForMenu clearly has five parameters?

CODE DETAIL
The writeSummaryLink method is:

protected void writeSummaryLink(int context, ClassDoc cd, ProgramElementDoc member) {
    ExecutableMemberDoc emd = (ExecutableMemberDoc)member;
    String name = emd.name();
    writer.strong();
    writer.printDocLinkForMenu(context, cd, (MemberDoc) emd, name, false);  // 94
    writer.strongEnd();
    writer.displayLength = name.length();
    writeParameters(emd, false);
}

Here's the method line 94 is calling:

public void printDocLinkForMenu(int context, ClassDoc classDoc, MemberDoc doc,
        String label, boolean strong) {
    String docLink = getDocLink(context, classDoc, doc, label, strong);
    print(deleteParameterAnchors(docLink));
}
Sentinel answered 31/5, 2010 at 20:34 Comment(0)
C
98

From section 4.3.2 of the JVM Spec:

Character     Type          Interpretation
------------------------------------------
B             byte          signed byte
C             char          Unicode character
D             double        double-precision floating-point value
F             float         single-precision floating-point value
I             int           integer
J             long          long integer
L<classname>; reference     an instance of class 
S             short         signed short
Z             boolean       true or false
[             reference     one array dimension

From section 4.3.3, Method descriptors:

A method descriptor represents the parameters that the method takes and the value that it returns:

MethodDescriptor:
        ( ParameterDescriptor* ) ReturnDescriptor

Thus,

(ILcom/sun/javadoc/ClassDoc;Lcom/sun/javadoc/MemberDoc;Ljava/lang/String;Z) Ljava/lang/String;

translates to:

A method with int, ClassDoc, MemberDoc, String and boolean as parameters, and which returns a String. Note that only reference parameters are separated with a semicolon, since the semicolon is part of their character representation.


So, to sum up:

Why there are four types in parentheses (ILcom/sun/javadoc/ClassDoc;Lcom/sun/javadoc/MemberDoc;Ljava/lang/String;Z) and one after the parentheses Ljava/lang/String; when the method printDocLinkForMenu clearly has five parameters?

There are five parameters (int, ClassDoc, MemberDoc, String, boolean) and one return type (String).

Croquet answered 31/5, 2010 at 20:57 Comment(5)
Same question, what would be ILcom/sun/javadoc/ClassDoc ?Sou
@Oscar Reyes: see my updated answer. I is int, L... is the ClassDoc.Croquet
I see. that's why the boolean is ...ing;Z because it is the last param, but the I being the first doesn't need ; Let's see... yeap, this method: public void x(int i, char c, boolean b, short s, long l, float f, double d ) is represented as: x (ICZSJFD)V +1Sou
Thank you. I deleted my class files, recompiled and no longer get the error message. Apparently, the mistake was an old class that that didn't get updated. I really appreciate the references to the JVM spec of type references, the explanation of why the error message has no semicolons after primitive types, and how to recognize the return type.Sentinel
I'm guessing a V after the last parentheses means the method doesn't have a return value (void).Chism
R
18

What does "ILcom" or "Z" mean?

Those are mapping types for native types. You can find an overview here.

Native Type    | Java Language Type | Description      | Type signature
---------------+--------------------+------------------+----------------
unsigned char  | jboolean           | unsigned 8 bits  | Z
signed char    | jbyte              | signed 8 bits    | B
unsigned short | jchar              | unsigned 16 bits | C
short          | jshort             | signed 16 bits   | S
long           | jint               | signed 32 bits   | I
long long      | jlong              | signed 64 bits   | J
__int64        |                    |                  |
float          | jfloat             | 32 bits          | F
double         | jdouble            | 64 bits          | D

In addition, the signature "L fully-qualified-class ;" would mean the class uniquely specified by that name; e.g., the signature "Ljava/lang/String;" refers to the class java.lang.String. Also, prefixing [ to the signature makes the array of that type; for example, [I means the int array type.


As to your next question:

Why there are four types in parentheses (ILcom/sun/javadoc/ClassDoc;Lcom/sun/javadoc/MemberDoc;Ljava/lang/String;Z) and one after the parentheses Ljava/lang/String; when the method printDocLinkForMenu clearly has five parameters?

Because you're not running the code you think you're running. The actually running code is trying to call exactly that method described in the error message, with actually five parameters (the I should be counted separately) and a String return type, but this method doesn't exist in the runtime classpath (while it was available in the compiletime classpath), hence this error. Also see the NoSuchMethodError javadoc:

Thrown if an application tries to call a specified method of a class (either static or instance), and that class no longer has a definition of that method.

Normally, this error is caught by the compiler; this error can only occur at run time if the definition of a class has incompatibly changed.

So, verify if you're actually running the right version of the code as you've posted in your question and are using the right dependencies in the runtime classpath and not having duplicate different versioned libraries in the classpath.

Update: the exception signifies that the actual code is (implicitly) trying to use the method like as follows:

String s = printDocLinkForMenu(context, cd, (MemberDoc) emd, name, false);

Because it is expecting a String outcome while it is declared void.

Rennold answered 31/5, 2010 at 20:49 Comment(8)
+1 but what's: ILcom/sun/javadoc/ClassDoc ? an intClassDoc? Or would it be a copy/paste error en be: [Lcom/sun/javadoc/ClassDoc ? or maybe it should've been I;Lcom/sun/javadoc/ClassDocSou
Do you know how a generic type looks like?Sou
@Oscar: sorry, not sure about IL type, this is the first time I see it. About Generics, it is compiletime syntactic sugar only and doesn't appear in bytecode.Rennold
It preserves the signature though, I see something like: Signature$Ljava/util/List<Ljava/lang/String;>;Sou
@Oscar: Hmm, that's nice to know.Rennold
See my answer for the IL part. I is int, the L is the start of the next reference parameter.Croquet
@JRL: ah so there's apparently actually no separator character. The ; which seems to be a separator character is actually part of the L type.Rennold
FWIW, I double-checked and ILcom/sun/javadoc/ClassDoc is not a copy/paste error.Sentinel

© 2022 - 2024 — McMap. All rights reserved.