解释java.lang.NoSuchMethodError消息


71

我收到以下运行时错误消息(以及堆栈跟踪的第一行,该行指向第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),而括号后有一种类型;当方法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));
}

Answers:


92

根据JVM Spec的4.3.2节

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

4.3.3节,方法描述符

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

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什么?
OscarRyz 2010年

@Oscar Reyes:请参阅我的最新答案。我是int,L ...是ClassDoc。
JRL

1
我懂了。这就是为什么布尔值是...ing;Z因为它是最后一个参数,但是我是第一个不需要。; 让我们看看...是的,这种方法:public void x(int i, char c, boolean b, short s, long l, float f, double d ) 表示为:x (ICZSJFD)V+1
OscarRyz 2010年

2
谢谢。我删除了我的课程文件,重新编译后不再收到错误消息。显然,该错误是一个未更新的旧类。我真的很感谢对JVM规范的引用类型的引用,对为什么错误消息在原始类型之后没有分号的解释,以及如何识别返回类型的解释。
dougkramer 2010年

3
我猜最后一个括号后面是V,表示该方法没有返回值(无效)。
pacoverflow

18

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

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

本机类型| Java语言类型| 描述 类型签名
--------------- + -------------------- + ------------- ----- + ----------------
未签名的字符| 布尔| 无符号8位| ž
签名字符| jbyte | 有符号8位| 乙
无符号的短| jchar | 无符号16位| C
短 jshort | 有符号16位| 小号
长| 金特| 有符号32位| 一世
长久| jlong​​ | 有符号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 返回类型,但这种方法不会在运行时类路径存在(而这是在现有编译时的类路径),因此会出现此错误。另请参阅NoSuchMethodErrorjavadoc

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

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

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

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

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

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


+1但是是什么ILcom/sun/javadoc/ClassDoc?一个intClassDoc?还是将复制/粘贴错误设为:[Lcom/sun/javadoc/ClassDoc?也许应该是I;Lcom/sun/javadoc/ClassDoc
OscarRyz 2010年

您知道泛型的外观吗?
OscarRyz 2010年

@Oscar:对不起,不确定IL类型,这是我第一次看到它。关于泛型,它仅是编译时语法糖,不会出现在字节码中。
BalusC,2010年

1
虽然它保留了签名,但我看到的类似于:Signature $ Ljava / util / List <Ljava / lang / String;>;
OscarRyz 2010年

2
@JRL:啊,所以实际上实际上没有分隔符。在;这似乎是一个分隔符实际上是部分L类型。
BalusC,2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.