Понимание того, как разрешить исключение «Несогласованные кадры карты стека»

Я получаю исключение при запуске веб-приложения, поскольку guice пытается создать упомянутый класс.

java.lang.VerifyError: Inconsistent stackmap frames at branch target 2770 in method com.aptusi.apps.magazine.api.servlet.internal.EditorServlet.service(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;Ljava/lang/String;Lcom/aptusi/persistence/runtime/framework/DboSession;)V at offset 200
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2483)
at java.lang.Class.getDeclaredConstructors(Class.java:1891)
at com.google.inject.spi.InjectionPoint.forConstructorOf(InjectionPoint.java:243)
at com.google.inject.internal.ConstructorBindingImpl.create(ConstructorBindingImpl.java:96)
at com.google.inject.internal.InjectorImpl.createUninitializedBinding(InjectorImpl.java:629)
at com.google.inject.internal.InjectorImpl.createJustInTimeBinding(InjectorImpl.java:845)
at com.google.inject.internal.InjectorImpl.createJustInTimeBindingRecursive(InjectorImpl.java:772)
at com.google.inject.internal.InjectorImpl.getJustInTimeBinding(InjectorImpl.java:256)
at com.google.inject.internal.InjectorImpl.getBindingOrThrow(InjectorImpl.java:205)
at com.google.inject.internal.InjectorImpl.getBinding(InjectorImpl.java:146)
at com.google.inject.internal.InjectorImpl.getBinding(InjectorImpl.java:66)
at com.google.inject.servlet.ServletDefinition.init(ServletDefinition.java:103)
at com.google.inject.servlet.ManagedServletPipeline.init(ManagedServletPipeline.java:82)
at com.google.inject.servlet.ManagedFilterPipeline.initPipeline(ManagedFilterPipeline.java:102)
at com.google.inject.servlet.GuiceFilter.init(GuiceFilter.java:172)`

Я знаю о параметрах -XX:-UseSplitVerifier и -noverify jvm, но я не хочу их использовать, так как хочу, чтобы весь код в этом проекте был как минимум java версии 7.

Для этого было бы полезно понять, где именно это происходит в моем коде, мне не ясно, что такое упомянутое смещение 200, но может ли оно быть связано с номером строки?

Также кто-нибудь знает, как я могу узнать java-версии всех классов в моем пути к классам, я использую maven, поэтому существует много зависимостей, поэтому я ищу автоматизированный способ поиска любых классов в пути к классам который мог быть скомпилирован в более низкую версию Java, чем 1.7?


person PiersyP    schedule 01.10.2013    source источник


Ответы (1)


Чтобы найти версию classfile, просто посмотрите на 8-й байт classfile. Это будет 51 для классов Java 7. Такой фреймворк, как ASM, сделает это за вас.

Что касается ошибки, это означает, что ваш classfile искажен. Как вы создали эти классы? Вы делали какие-либо манипуляции с байт-кодом? Если это так, у вас, вероятно, есть ошибка в вашем коде.

person Antimony    schedule 01.10.2013
comment
Спасибо Антимони, проблема в том, что этот проект зависит примерно от 100 банок, поэтому мне нужен способ быстро проверить, что все классы во всех банках соответствуют определенной версии. - person PiersyP; 01.10.2013
comment
Просто напишите скрипт Python (при условии, что вы знаете, где находятся банки). - person Antimony; 01.10.2013
comment
Кажется, это единственный способ проверить это, хотя я удивлен, что для этого еще нет инструмента. - person PiersyP; 02.10.2013
comment
Знаете ли вы, как смещение связано с номером строки в файле класса? - person PiersyP; 02.10.2013
comment
@PiersyP Это не имеет ничего общего с номерами строк. Это относится к фактическому смещению в байт-коде. - person Antimony; 02.10.2013
comment
Приветствую Антимония, в конце концов я выбрал немного более специальное решение, заключающееся в постепенном комментировании кода, чтобы сузить круг виновника. Оказалось, что это зависимость org.json:json. - person PiersyP; 04.10.2013
comment
Этот баг - боль моего существования. Он продолжает появляться случайным образом, так как я начал компилировать свой проект с помощью JDK 7, используя eclipse, maven, m2eclipse, движок приложения. Раньше мне просто нужно было убедиться, что все банки были помещены maven в папку lib. Но в последнее время это происходит, когда я вызываю определенные статические методы в своем коде! и все это часть того же проекта, созданного с помощью Java 7. - person ZiglioUK; 18.10.2013
comment
@ZiglioNZ Если вы не выполняете модификацию байт-кода во время выполнения, проблема в том, что один или несколько ваших файлов классов искажены. Лучше всего написать скрипт для загрузки каждого класса и записать, какие из них не удалось загрузить. - person Antimony; 18.10.2013
comment
@Antimony, это всегда один и тот же статический метод, который терпит неудачу. Но случайно не получается. Иногда я перестраиваю зависимость, и она исчезает, иногда нет ни на сервере разработки, ни на рабочем сервере gae. Я не понимаю, что GAE SDK делает во время выполнения, он может внести некоторые изменения в байт-код. Я нашел отчет об ошибке за 2012 год, который показал, что ошибка происходит с компилятором Eclipse, поэтому я не знаю. Какое-то странное взаимодействие - person ZiglioUK; 18.10.2013
comment
Это просто мой мозг новичка делает предположение, но у вас есть усилитель ядра данных? Я понимаю, что это изменяет байт-код. - person slugmandrew; 18.10.2013
comment
@ZiglioNZ GAE использует пользовательскую среду, что может вызвать проблемы. Однако тот факт, что он также появляется на вашем сервере разработки, показывает, что это не проблема GAE. В любом случае, что делает этот статический метод? - person Antimony; 18.10.2013
comment
@Antimony У меня есть два или три статических метода для сохранения больших файлов в BlobStore. Я вошел в систему с помощью Windows, и все мои файлы находятся в Linux, поэтому я вернусь к вам с подписью метода. Также я установил программу просмотра байт-кода, интересно, как я могу обнаружить несоответствие карты стека. Это между вызывающим и вызываемым? спасибо за интерес, очень приятно! - person ZiglioUK; 19.10.2013
comment
@ZiglioNZ Вы используете стандартную JVM Hotspot? Вы сами компилируете com.google.appengine.api.blobstore.BlobKey или используете предоставленный classfile? Также вы можете опубликовать файл класса для BlobKey? - person Antimony; 20.10.2013
comment
@Antimony Ну, это интересно. BlobKey является частью GAE SDK, и в файле класса показана // версия класса 50.0 (50) - person ZiglioUK; 21.10.2013
comment
Я обновил свою суть этим классом. Он поставляется с готовыми JAR-файлами GAE SDK. Я работаю с последней средой выполнения Oracle java 7. Интересно, однако, что если эта ошибка возникает в моей системе разработки, она также возникает на серверах GAE. Я не совсем уверен, какую версию Java они используют и какого поставщика используют. - person ZiglioUK; 21.10.2013
comment
@Antimony Хорошо, когда верификатор времени выполнения работает правильно? Я должен проверить. Кроме того, мне интересно, как работает верификатор в случае, если некоторые классы имеют версию 51 с картой стека, а некоторые другие - нет, GAE SDK. Это означает, что верификатор должен вернуться к классическому двухпроходному методу. - person ZiglioUK; 21.10.2013
comment
Hotspot возвращается к обычной проверке логических выводов для файлов классов до версии 51.0. Это то, что он должен делать. - person Antimony; 22.10.2013
comment
@Antimony Итак, скажем, моя карта стека класса 51.0 содержит параметры 50.0 и 51.0, работает устаревший верификатор байт-кода, и что не получается? В любом случае, я не знаю, что я сделал, но проблема исчезла. Я обратился к одной из зависимостей и убедился, что они используют одну и ту же версию GAE SDK. Это не оставляет меня с хорошим чувством, потому что я действительно не понял, что вызвало проблему. Боюсь, на данном этапе это выше моего понимания. Я ценю вашу помощь! - person ZiglioUK; 23.10.2013
comment
@Ziglio, что вы подразумеваете под версиями параметров? Версия является свойством всего classfile. - person Antimony; 23.10.2013
comment
@Antimony Я имею в виду классы, перечисленные во фрейме StackMap. Некоторые из них 51.0, а другие (из GAE SDK) 50.0. - person ZiglioUK; 24.10.2013
comment
@Ziglio Это вообще не имеет значения. Вы можете поместить туда имя класса 45.0 для всех забот JVM. Вы даже можете поместить случайный мусор, который вообще не относится к реальному классу, хотя вы, вероятно, получите ошибку загрузчика, когда виртуальная машина попытается загрузить указанный класс. - person Antimony; 24.10.2013
comment
@Antimony, я думал, что верификатор будет рекурсивно проверять все карты стека классов в картах стека, но, возможно, я не понимаю, как работает верификатор. Одна из моих зависимостей была создана для другой версии GAE SDK. Должно быть, где-то в цепочке произошел сбой проверки байт-кода. - person ZiglioUK; 24.10.2013
comment
@Ziglio Проверяет все карты стека в загружаемом классе. Иногда проверка приводит к загрузке других классов, и в этом случае эти классы также будут проверены. Но это в основном отдельный процесс. В любом случае, есть ли у вас минимальный набор файлов классов, который вызывает ошибку? Если это так, я мог бы взглянуть на них, чтобы увидеть, могу ли я понять, в чем проблема. - person Antimony; 24.10.2013
comment
@Antimony Я попытаюсь воспроизвести ошибку. Могу отправить вам личное сообщение здесь или на github - person ZiglioUK; 25.10.2013