【问题标题】:Interpreting java.lang.NoSuchMethodError message解释 java.lang.NoSuchMethodError 消息
【发布时间】:2011-02-26 02:45:04
【问题描述】:

我收到以下运行时错误消息(连同堆栈跟踪的第一行,它指向第 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)

writeSummaryLink 的第 94 行如下所示。

问题
“ILcom”或“Z”是什么意思?
为什么括号里有四种类型 (ILcom/sun/javadoc/ClassDoc;Lcom/sun/javadoc/MemberDoc;Ljava/lang/String;Z) 和括号后面的一个 Ljava/语言/字符串; 当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));
}

【问题讨论】:

    标签: java nosuchmethoderror


    【解决方案1】:

    来自 JVM 规范的 section 4.3.2

    字符类型解释 ------------------------------------------ B 字节 有符号字节 C char Unicode 字符 D double 双精度浮点值 F float 单精度浮点值 我 int 整数 J long long 整数 L;引用类的实例 S 短 有符号短 Z 布尔值 true 或 false [引用一维数组

    来自section 4.3.3, Method descriptors

    一个方法描述符表示该方法接受的参数和它返回的值:

    MethodDescriptor:
            ( ParameterDescriptor* ) ReturnDescriptor
    

    因此,

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

    翻译为:

    一个以intClassDocMemberDocStringboolean为参数的方法,它返回一个String。请注意,只有引用参数用分号分隔,因为分号是其字符表示的一部分。


    所以,总结一下:

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

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

    【讨论】:

    • 同样的问题,ILcom/sun/javadoc/ClassDoc 会是什么?
    • @Oscar Reyes:查看我的更新答案。 I 是 int,L... 是 ClassDoc。
    • 我明白了。这就是为什么布尔值是...ing;Z 因为它是最后一个参数,但我是第一个不需要; 让我们看看......是的,这个方法:public void x(int i, char c, boolean b, short s, long l, float f, double d ) 表示为:x (ICZSJFD)V +1
    • 谢谢。我删除了我的类文件,重新编译并且不再收到错误消息。显然,错误是一个没有更新的旧类。非常感谢对类型引用的JVM规范的引用,解释了为什么错误消息在原始类型之后没有分号,以及如何识别返回类型。
    • 我猜最后一个括号后面的 V 表示该方法没有返回值 (void)。
    【解决方案2】:

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

    这些是本机类型的映射类型。您可以找到概览here

    原生类型 | Java 语言类型 |说明 |类型签名 ---------------+--------------------+------------- -----+---------------- 无符号字符 | jboolean |无符号 8 位 | Z 签名字符 | jbyte |有符号的 8 位 |乙 无符号短 | jchar |无符号 16 位 | C 短 |短片 |带符号的 16 位 |小号 长 |金特 |带符号的 32 位 |一世 长长|金龙 |有符号的 64 位 | Ĵ __int64 | | | 浮动 | jfloat | 32 位 | F 双 | jdouble | 64 位 | D

    此外,签名"L fully-qualified-class ;" 表示该名称唯一指定的类;例如,签名"Ljava/lang/String;" 指的是类java.lang.String。此外,在签名前加上 [ 会生成该类型的数组;例如,[I 表示 int 数组类型。


    关于你的下一个问题:

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

    因为您没有运行您认为正在运行的代码。 实际上正在运行的代码正试图准确调用错误消息中描述的那个方法,实际上有五个参数(I 应该单独计算)和一个String return 类型,但是这个方法没有'在运行时类路径中不存在(而它在编译时类路径中可用),因此出现此错误。另见NoSuchMethodError javadoc

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

    通常,编译器会捕获此错误;如果类的定义发生了不兼容的更改,则此错误只会在运行时发生。

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

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

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

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

    【讨论】:

    • +1 但什么是:ILcom/sun/javadoc/ClassDoc?一个intClassDoc?还是会是复制/粘贴错误:[Lcom/sun/javadoc/ClassDoc?或者应该是I;Lcom/sun/javadoc/ClassDoc
    • 你知道泛型类型是什么样子的吗?
    • @Oscar:抱歉,不清楚IL的类型,第一次见。关于泛型,它只是编译时语法糖,不会出现在字节码中。
    • 它保留了签名,但我看到类似:Signature$Ljava/util/List;
    • @JRL:啊,所以显然实际上没有分隔符。 ; 似乎是分隔符,实际上是 L 类型的一部分。
    猜你喜欢
    • 2022-01-06
    • 2011-02-02
    • 2016-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多