Фалшива NoSuchMethodError

Получаваме NoSuchMethodError в един от нашите класове на прост метод за получаване. Странното е, че можем да отстраняваме грешки в кода и да видим възникването на грешка в дебъгера (като преминем през съответния ред), но можем също да използваме IDE (IntelliJ IDEA), за да видим, че методът наистина съществува.

Извършването на xxxx.getYYY() оценява добре чрез оценителя на IDE изрази. И отивайки xxxx.getClass().getMethods() можем да видим метода getYYY() в списъка. Опитахме да изчистим всички вградени файлове, IDE изходни директории, IDE кешове, рестартиране и т.н. и изглежда нищо не помага.

Бих разбрал, че NoSuchMethodError ще се случи, ако бяхме компилирали срещу нещо, но след това по време на изпълнение беше намерен различен Jar/клас. Но това не ми обяснява защо по време на изпълнение, докато дебъгваме във въпросния ред, можем да видим, че методът е там, но прекрачването на реда хвърля изключението.

Опитах да възпроизвеждам на друга машина, но не се възпроизвежда.

Някой има ли представа какво може да се случва тук?


person Mike Q    schedule 22.06.2011    source източник
comment
имате ли собствена йерархия на зареждащия клас?   -  person Suraj Chandran    schedule 22.06.2011
comment
Бихте ли могли да редактирате въпроса и да добавите (пълно) проследяване на стека?   -  person Wivani    schedule 22.06.2011
comment
Какво прави този ред/метод и сигурни ли сте, че не този метод хвърля NoSuchMethodError?   -  person Kaj    schedule 22.06.2011
comment
Можете ли да дадете повече информация за настройката на вашия проект? Стартирате ли приложението си чрез IntelliJ или от командния ред?   -  person Jens Hoffmann    schedule 22.06.2011
comment
@Suraj, не само стандартното средство за зареждане на класове. Просто използвайки основния Spring като контейнер без умни неща.   -  person Mike Q    schedule 22.06.2011
comment
@Kaj, изключението показва точния метод със сигнатура, така че е доста ясно кой метод причинява проблема   -  person Mike Q    schedule 22.06.2011
comment

Вашата основна функция се нуждае от този точен подпис: int main(int, char**)

  -  person Mike Q    schedule 22.06.2011


Отговори (2)


Най-вероятно не изпълнявате същите версии на код в IntelliJ като това, което редактирате. Получавам този проблем често с много maven проекти, отворени наведнъж с различни версии в зависимости от това, което редактирам. IntelliJ може да се обърка (или аз се обърквам коя версия всъщност използвам)

person Peter Lawrey    schedule 22.06.2011
comment
Да, това беше първата ми мисъл, но това не обяснява способността за рефлективно виждане на метода по време на изпълнение. - person Mike Q; 22.06.2011
comment
Методът може да е леко различен, напр. типът връщане може да е различен. За JVM всички параметри и тип на връщане имат значение. - person Peter Lawrey; 22.06.2011
comment
@Петър. Това е интересно. Повикващият има ли пълна информация за метода на извикване, включително типовете параметри и типа на връщане? Бях под впечатлението, че JVM разрешава по време на изпълнение и ще хвърли NoSuchMethodError, ако стойностите на параметрите не могат да бъдат принудени към целеви метод? - person Mike Q; 22.06.2011
comment
@Mike Q, това прави компилаторът. Ако промените типа на връщане от long на int, трябва да прекомпилирате извикващите, въпреки че не е необходимо да променяте кода. - person Peter Lawrey; 22.06.2011
comment
@Peter, мисля, че беше прав с типа на връщането. Променихме го да връща Integer вместо int в някакъв момент и мисля, че беше взет стар буркан. Много трудно се забелязва в дебъгера тази малка разлика. - person Mike Q; 23.06.2011
comment
Съгласен съм, тъй като Java не използва върнатия тип като част от подписа и Class.getMethod(Class[]) също не го използва, лесно е да забравите JVM. - person Peter Lawrey; 23.06.2011
comment
Може да намерите тази статия за интересна. Показва как можете да претоварвате чрез типове връщане в Java. vanillajava.blogspot.com/2011/ 02/ - person Peter Lawrey; 23.06.2011

NoSuchMethodError - Това се случва най-вече по време на изпълнение. Попаднах на тази грешка, причината бяха несъвместими версии на asm и cglib библиотеки в моя клас път.

Библиотеките asm и cglib се използват от много рамки като hibernate, spring, hadoop за манипулиране на байт код по време на изпълнение.

Classloader винаги препраща към първата версия на jar в classpath.

person LearningAboutTech    schedule 03.09.2015