Hacker News Digest

Тег: #bytecode

Постов: 3

JVM exceptions are weird: a decompiler perspective (purplesyringa.moe)

Автор исследует сложность обработки исключений JVM при декомпиляции Java-байткода. Изначально предполагалось, что метод декомпиляции управляющих потоков, разработанный автором, можно легко расширить для обработки исключений, но оказалось, что множество крайних случаев значительно усложняют задачу. JVM использует стековую архитектуру, где обычные управляющие конструкции реализуются явно, а исключения обрабатываются неявно через отдельную таблицу исключений. Эта таблица связывает регионы инструкций с обработчиками, но JVM не требует соблюдения иерархической вложенности обработчиков, что приводит к пересекающимся диапазонам и нарушает интуитивные ожидания.

Реальные Java-файлы часто содержат такие "неестественные" конструкции, что делает проблему важной для любого декомпилятора. Автор также отмечает сложность обработки try...finally блоков, где код finally должен выполняться независимо от возникновения исключения, но передача управления после его завершения зависит от контекста. Эти особенности байткода и компилятора javac создают значительные препятствия для создания корректного декомпилятора, особенно при попытке восстановления исходной структуры кода.

by vrnvu • 04 ноября 2025 г. в 09:08 • 146 points

ОригиналHN

#java#jvm#decompilation#bytecode#exceptions#javac#csharp

Комментарии (46)

  • Обсуждение началось с примера кода, который выглядит как баг, но на самом деле является корректным поведением в Java и других языках, где finally блок не может перехватить return/throw, но может перехватить continue/break.
  • Участники обсудили, что в действительности это не баг, а фича, и что в большинстве языков finally не может перехватить return/throw, но может перехватить continue/break.
  • Обсуждались также вопросы, что в некоторых языках, таких как C#, такие конструкции вообще не допускаются.
  • Также было отмечено, что в Java 25 такой код будет компилироваться и работать, но в более ранних версиях Java это вызовет ошибку компиляции.

Fernflower Java Decompiler (github.com)

FernFlower — это декомпилятор от JetBrains, преобразующий байт-код Java обратно в читаемый исходный код. Он интегрирован в IntelliJ IDEA и известен высокой точностью восстановления логики, включая обработку исключений, циклов и локальных переменных. Инструмент активно используется разработчиками для анализа и отладки скомпилированных приложений, когда исходники недоступны.

Проект открыт под лицензией Apache 2.0, что позволяет свободно использовать и модифицировать код. Несмотря на конкуренцию с другими декомпиляторами, FernFlower выделяется качеством output’а и поддержкой современных функций Java. Практический плюс — его встроенная доступность в популярной IDE, что ускоряет работу без необходимости установки сторонних утилит.

by bartekpacia • 25 сентября 2025 г. в 20:20 • 112 points

ОригиналHN

#java#decompiler#intellij-idea#jetbrains#apache-2.0#bytecode#jadx#dnspy#llm#refactoring

Комментарии (36)

  • Обсуждается Java-декомпилятор Fernflower (Vineflower), его история, технические особенности и превосходство над аналогами.
  • Участники делятся опытом использования Fernflower и других инструментов (jadx для Android, dnSpy для .NET), отмечая их эффективность.
  • Поднимаются технические вопросы: возможность повторной компиляции, работа с обфусцированным кодом, корректность отображения строк.
  • Обсуждается потенциальное применение LLM для присвоения осмысленных имен переменным и рефакторинга декомпилированного кода.
  • Упоминается создатель Fernflower и его другие проекты, а также доступные GUI-интерфейсы и веб-инструменты для работы с JAR-файлами.

How Ruby executes JIT code (railsatscale.com)

Где живёт JIT-код

Ruby не выбрасывает байт-код — он остаётся в ISEQ. В структуре метода поле jit_entry либо NULL (интерпретатор), либо адрес скомпилированной машинной функции. Байт-код нужен для деоптимизации.

Как Ruby запускает JIT

Перед каждым вызовом метода VM проверяет jit_entry. Если указатель не нулевой — переход на него, иначе обычный интерпретатор. Одна проверка, один jmp.

Когда компилировать

ZJIT ждёт 25 вызовов для профилирования и 30 для компиляции (числа настраиваются). Пока счётчик jit_entry_calls не достигнет порога, метод работает в байт-коде.

Почему возвращаются к интерпретатору

JIT делает упрощающие предположения (типы, классы). Если они нарушаются — контроль возвращается к байт-коду, который всегда корректен. Это «деоптимизация»: быстро, но безопасно.

by ciconia • 09 сентября 2025 г. в 21:01 • 128 points

ОригиналHN

#ruby#jit#mri#jruby#truffleruby#just-in-time-compilation#dynamic-typing#interpreter#tiered-compilation#bytecode

Комментарии (20)

  • Участники обсуждают, возможно ли ускорить Ruby с помощью фонового JIT, который постепенно перекомпилирует методы по мере накопления профильной информации (tiered compilation уже есть в .NET и JS-движках).
  • Предложен снимок «прогретой» VM для мгновенного старта, но проблема — глобальное состояние C-библиотек; Emacs делает это через unexec.
  • MRI Ruby не распараллеливает потоки и не дружит с JIT: язык позволяет динамически менять классы, что ломает оптимизации.
  • Альтернатива — JRuby/TruffleRuby на JVM, но они теряют часть динамики и накладывают ограничения JVM.
  • Соглашение: Ruby вряд ли догонит Java по скорости из-за динамической типизации и дизайна языка.