Интерпретация сообщения java.lang.NoSuchMethodError

Я получаю следующее сообщение об ошибке времени выполнения (вместе с первой строкой трассировки стека, которая указывает на строку 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 writeSummaryLink показана ниже.

ВОПРОСЫ
Что означает "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));
}

person dougkramer    schedule 31.05.2010    source источник


Ответы (2)


Из раздела 4.3.2 спецификации JVM:

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;

переводится как:

Метод с int, ClassDoc, MemberDoc, String и boolean в качестве параметров, возвращающий String. Обратите внимание, что только ссылочные параметры разделяются точкой с запятой, поскольку точка с запятой является частью их символьного представления.


Итак, подводя итог:

Почему в скобках четыре типа (ILcom/sun/javadoc/ClassDoc;Lcom/sun/javadoc/MemberDoc;Ljava/lang/String;Z) и один после скобок Ljava/lang/String; когда у метода printDocLinkForMenu явно пять параметров?

Имеется пять параметров (int, ClassDoc, MemberDoc, String, boolean) и один тип возвращаемого значения (String).

person JRL    schedule 31.05.2010
comment
Тот же вопрос, что будет ILcom/sun/javadoc/ClassDoc ? - person OscarRyz; 01.06.2010
comment
@Oscar Reyes: см. мой обновленный ответ. I — это int, L… — это ClassDoc. - person JRL; 01.06.2010
comment
Я понимаю. вот почему логическое значение равно ...ing;Z, потому что это последний параметр, но I, будучи первым, не нуждается в ; Давайте посмотрим... да, этот метод: public void x(int i, char c, boolean b, short s, long l, float f, double d ) представлен как: x (ICZSJFD)V +1 - person OscarRyz; 01.06.2010
comment
Спасибо. Я удалил свои файлы классов, перекомпилировал и больше не получаю сообщение об ошибке. Судя по всему, ошибкой был старый класс, который не обновлялся. Я очень ценю ссылки на спецификацию ссылок на типы JVM, объяснение того, почему в сообщении об ошибке нет точки с запятой после примитивных типов, и как распознать возвращаемый тип. - person dougkramer; 20.06.2010
comment
Я предполагаю, что V после последних скобок означает, что метод не имеет возвращаемого значения (void). - person pacoverflow; 24.07.2013

Что означает 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

Кроме того, сигнатура "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);

Потому что он ожидает результат String, пока объявлен void.

person BalusC    schedule 31.05.2010
comment
+1 а что такое: ILcom/sun/javadoc/ClassDoc ? intClassDoc? Или это будет ошибка копирования/вставки: [Lcom/sun/javadoc/ClassDoc ? или, может быть, это должно было быть I;Lcom/sun/javadoc/ClassDoc - person OscarRyz; 01.06.2010
comment
Вы знаете, как выглядит общий тип? - person OscarRyz; 01.06.2010
comment
@Oscar: извините, не уверен насчет типа IL, впервые вижу. Что касается дженериков, это синтаксический сахар только во время компиляции, и он не появляется в байт-коде. - person BalusC; 01.06.2010
comment
Однако он сохраняет подпись, я вижу что-то вроде: Signature$Ljava/util/List‹Ljava/lang/String;›; - person OscarRyz; 01.06.2010
comment
@Oscar: Хм, приятно это знать. - person BalusC; 01.06.2010
comment
Смотрите мой ответ для части IL. I — это int, L — это начало следующего ссылочного параметра. - person JRL; 01.06.2010
comment
@JRL: ах, так что, по-видимому, на самом деле нет символа-разделителя. ;, который кажется символом-разделителем, на самом деле является частью типа L. - person BalusC; 01.06.2010
comment
FWIW, я дважды проверил, и ILcom/sun/javadoc/ClassDoc не является ошибкой копирования/вставки. - person dougkramer; 01.06.2010