Interpreting java.lang.NoSuchMethodError message

2022-08-31 13:10:21

我收到以下运行时错误消息(以及堆栈跟踪的第一行,指向第 94 行)。我试图弄清楚为什么它说不存在这样的方法。

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)

写摘要链接的第 94 行如下所示。

问题
“ILcom”或“Z”是什么意思?
为什么括号中有四种类型(ILcom/sun/javadoc/ClassDoc;Lcom/sun/javadoc/MemberDoc;Ljava/lang/String;Z) 和括号 Ljava/lang/String 后面的一个;当方法 printDocLinkForMenu 明显有五个参数时?

代码详细信息
writeSummaryLink 方法是:

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);
}

下面是第 94 行正在调用的方法:

public void printDocLinkForMenu(int context, ClassDoc classDoc, MemberDoc doc,
        String label, boolean strong) {
    String docLink = getDocLink(context, classDoc, doc, label, strong);
    print(deleteParameterAnchors(docLink));
}

答案 1

从 JVM 规范的 4.3.2 节中

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

4.3.3 节,方法描述符

方法描述符表示该方法采用的参数及其返回的值:

MethodDescriptor:
        ( ParameterDescriptor* ) ReturnDescriptor

因此

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

翻译为:

将 、 、 和 作为参数的方法,它返回 .请注意,只有引用参数用分号分隔,因为分号是其字符表示的一部分。intClassDocMemberDocStringbooleanString


所以,总结一下:

为什么括号中有四种类型(ILcom/sun/javadoc/ClassDoc;Lcom/sun/javadoc/MemberDoc;Ljava/lang/String;Z) 和括号 Ljava/lang/String 后面的一个;当方法 printDocLinkForMenu 明显有五个参数时?

有五个参数(int,ClassDoc,MemberDoc,String,boolean)和一个返回类型(String)。


答案 2

“ILcom”或“Z”是什么意思?

这些是本机类型的映射类型。您可以在此处找到概述。

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

此外,签名将是指由该名称唯一指定的类;例如,签名是指类 。此外,签名的前缀使该类型的数组;例如,表示 int 数组类型。"L fully-qualified-class ;""Ljava/lang/String;"java.lang.String[[I


至于你的下一个问题:

为什么括号中有四种类型(ILcom/sun/javadoc/ClassDoc;Lcom/sun/javadoc/MemberDoc;Ljava/lang/String;Z) 和括号 Ljava/lang/String 后面的一个;当方法 printDocLinkForMenu 明显有五个参数时?

因为你没有运行你认为你正在运行的代码。实际运行的代码正在尝试调用错误消息中描述的方法,实际上有五个参数(应单独计数)和一个返回类型,但此方法在运行时类路径中不存在(尽管它在编译时类路径中可用),因此存在此错误。另请参阅NoSuchMethodError javadocIString

如果应用程序尝试调用某个类(静态或实例)的指定方法,并且该类不再具有该方法的定义,则抛出该值。

通常,编译器会捕获此错误;仅当类的定义发生不兼容更改时,此错误才会在运行时发生。

因此,请验证是否确实运行了问题中发布的正确版本的代码,并在运行时类路径中使用了正确的依赖项,并且在类路径中没有重复的不同版本化库。

更新:异常表示实际代码(隐式)尝试使用如下所示的方法:

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

因为它在声明时期待结果。Stringvoid


推荐