Начинающий
- Статус
- Онлайн
- Регистрация
- 5 Июн 2025
- Сообщения
- 501
- Реакции
- 24
Данный гайд несет в себе цель понять каким образом читать стак-трейсы ошибок в Java, краш-репорты Minecraft и немного информации о том, куда можно ориентироваться при чтении JVM краш-логов (спойлер - без дебага это будет не просто).
Умение читать ошибки, и понимать что они означают - это совсем не сложно. В данном гайде мы рассмотрим различные стак-трейсы, попробуем их разбить на логическую составляющую и будем учится находить места и причины подобных ошибок. Реальная "теория" в этом гайде будет преимущественно опускаться, дабы сделать упор на более простое восприятие материала.
Раздел 1. Стак-трейсы
По простому stacktrace'ы можно описать как список вызванных функций начиная от стартовой точки выполнения потока. Вместе с этим, stacktrace'ы обычно содержат в себе названия ошибок которые были "выкинуты" в процессе выполнения приложения, я думаю в 99% случаев stacktrace'ы вы будете видеть из-за случившихся ошибок.
Выглядят stacktrace'ы таким образом:
Давайте разберем его структурно на части.
Так-же stacktrace'ы могут содержать несколько ошибок подряд. Выглядит это примерно так:
В данном случае первой ошибкой которая случилась является
Если мы посмотрим на код который выдал такой stacktrace, мы увидим что
Для закрепления информации, предлагаю разобрать несколько реальных ошибок не связанных с Minecraft:
Почему за ошибку можно посчитать
Не стоит бояться ошибок и stacktrace'ов, они не страшные и как правило далеко не большие (если, конечно, вы не работаете в энтерпрайзе
)
Раздел 2. Краш-репорты и Minecraft
Crash-report Minecraft'а де-факто является тем-же stacktrace'ом, дополнительно украшенным информацией об системе, вашем устройстве и веселым "комментарием" разработчиков игры. Crash-report'ы в Minecraft практически всегда "многоуровневые"(имеют несколько ошибок в stacktrace'е), поэтому важно анализировать его весь, т.к. фактическая ошибка может быть где угодно. Поскольку это по большей части будут те-же stacktrace'ы, этот раздел будет больше про анализ ошибок которые можно встретить на этом форуме в разделе Minecraft'а, и пояснения как самостоятельно приходить к их решению.
Для начала давайте ознакомимся со структурой crash-report'а:
В краш репорте есть вполне интересные блоки на которые можно обратить внимание, если наша проблема зависима от сборки JVM или комплектующих компьютера (к примеру не проявляется с видеокартами AMD Radeon, но проявляется на видеоадаптерах Intel Iris). Что-ж за они?
Как правило, crash-report'ов более чем достаточно для решения ошибки, но иногда случаются ошибки которые могут поломать механизм записи crash-report'ов. В таком случае необходимо открывать логи клиента/сервера и разбираться уже с ними, т.к. часто информация с crash-report'а дублируется и в логи, а если и нет - то как минимум сама ошибка там присутствовать обязана (если ваша ошибка не связана с крашем всей JVM).
Далее рассмотрим примеры ошибок и их решения. Рассматривать мы их будем в порядке начиная с самых простых, заканчивая более сложными.
Раздел 3. JVM краш-логи
Пришло время самой тяжелой темы, которую даже я до сих пор особо не понимаю, но с которой мне приходится работать чуть ли не каждый день. JVM краш-логи (они-же файлы формата
Обратим внимание всего на 2 блока, и рассмотрим только их. Если-же вам интересно как-же читать более подробно подобные краш-логи, вот вам два видео с конференций, там более подробно про это рассказывают:
Нам интересно следующее:
Думаю взглянув один раз, возникнет чувство что это чем-то похоже на обычный stacktrace джавы. Собственно по нему можно ориентироваться дабы искать проблемы, просто если проблема в нативной библиотеке, а вы запустились без запущенного дебаггера - найти проблему будет сильно сложнее. Ниже я опишу пока-что 1 из случаев когда получилось обойтись без дебаггеров и понять где и как происходит проблема прибегая лишь к оффициальной документации и исходникам библиотек.
Заключение
Спасибо за прочтение.
На самом деле тема не то что-бы большая(если не брать в учёт JVM краш-логи), но примерами её можно раздувать бесконечно. Бояться исключений, ошибок, краш-репортов и краш-логов не нужно, это обычные вещи цель которых не дать случится ошибкам похлеще(вроде синего экрана, либо зависания намертво).
Если у вас есть какие-то интересные примеры stacktrace'ов, crash-report'ов или JVM краш-логов, не стесняйтесь ими делиться, самое интересное я добавлю в статью указав ваш тег!
Умение читать ошибки, и понимать что они означают - это совсем не сложно. В данном гайде мы рассмотрим различные стак-трейсы, попробуем их разбить на логическую составляющую и будем учится находить места и причины подобных ошибок. Реальная "теория" в этом гайде будет преимущественно опускаться, дабы сделать упор на более простое восприятие материала.
Раздел 1. Стак-трейсы
По простому stacktrace'ы можно описать как список вызванных функций начиная от стартовой точки выполнения потока. Вместе с этим, stacktrace'ы обычно содержат в себе названия ошибок которые были "выкинуты" в процессе выполнения приложения, я думаю в 99% случаев stacktrace'ы вы будете видеть из-за случившихся ошибок.
Выглядят stacktrace'ы таким образом:
Java stacktrace:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "str" is null
at com.example.MyClass.myMethod(MyClass.java:10)
at com.example.MyClass.main(MyClass.java:5)
Давайте разберем его структурно на части.
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "str" is null
- Первую строку можно так-же разбить на несколько элементов:Exception in thread "main"
- Говорит нам об том, что ошибка произошла в потоке с названиемmain
java.lang.NullPointerException
- Тип(класс) ошибки которая случилась. В данном случае это NullPointerException (NPE), означающий что где-то у нас вместо существующего объекта был использован null, чего не должно было случится.Cannot invoke "String.length()" because "str" is null
- Описание ошибки, дословный перевод которогоНевозможно выполнить "String.length()" поскольку "str" является null
. Подобное описание должно послужить одним из главнейших ориентиров, т.к. оно буквально описывает причину по которой возникла ошибка в коде. А именно выполнился следующий код:
Java code:String str = null; // Переменная имеет значение null /* ... */ str.length(); // Пытаемся вызвать функцию length() у переменной со значением null
at com.example.MyClass.myMethod(MyClass.java:10)
. После ошибки, у нас идут функции которые вызывались поочередно. От самой последней расположенной в начале, до самой первой расположенной в самом конце. В данном случае, пример кода приведённый выше (сstr.length()
) должен находится в функции указанной в этой строке, в пакетеcom.example
, классеMyClass
, в функцииmyMethod(...)
. Дополнительно у на есть сведения об исходном файле, и строке этого файла в которой находится код вызвавший ошибку (ФайлMyClass.java
, строка10
).at com.example.MyClass.main(MyClass.java:5)
. Последняя строка нашего stacktrace'а, и вторая строка с вызовом функции. Если функция не самая первая после ошибки в stacktrace'е, это значит что сама ошибка случилась не на ней, но указанная функция является звеном в списке вызовов при котором случилась ошибка. Если проще - Функцияmain(...)
вызвала функциюmyMethod(...)
, которая в свою очередь уже выкинула ошибку.
Так-же stacktrace'ы могут содержать несколько ошибок подряд. Выглядит это примерно так:
Java stacktrace:
java.lang.RuntimeException: Failed due to exception.
at org.example.MyClass.myMethod(Test.java:10)
at org.example.MyClass.main(Test.java:5)
Caused by: java.lang.NullPointerException: myField1 is null
at org.example.MyClass.myMethodWithNull(Test.java:16)
at org.example.MyClass.myMethod(Test.java:10)
... 2 more
В данном случае первой ошибкой которая случилась является
NullPointerException
, после которой случилась ошибка RuntimeException
. Как так? Всё просто!Если мы посмотрим на код который выдал такой stacktrace, мы увидим что
NullPointerException
попал в try-catch блок, который выбрасывает RuntimeException
если случается ошибка (На эту мысль так-же может навести "Caused by:" на 4-й строке stacktrace'а).
Java code (Test#myMethod(...)):
try {
myMethodWithNull(); // Выбрасывает NullPointerException
} catch (Exception exception) {
throw new RuntimeException("Failed due to exception.", exception);
}
Для закрепления информации, предлагаю разобрать несколько реальных ошибок не связанных с Minecraft:
- Пример ошибки при попытке получить значение массива с индексом, который превышает размер массива. (Если размер массива - 5 элементов, то последний его индекс будет 4, т.к. индексы массивов начинаются с нуля).
Java stacktrace:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5 at com.example.Main.main(Main.java:6)
- Пример ошибки при попытке создать
ArrayList
с некорректным аргументом(значением начального размера "-1"). В основном подобное регулируется документацией, где объясняется какие данные можно передавать в функцию как параметр, а какие лучше не стоит.Java stacktrace:Exception in thread "main" java.lang.IllegalArgumentException: Negative capacity: -1 at java.base/java.util.ArrayList.<init>(ArrayList.java:153) at com.example.Main.main(Main.java:3)
- Пример ошибки валидации байткода (особенно популярно при написании своих обфускаторов, которые "захламляют" байткод некорректными опкодами, в следствии чего JVM не способна прочитать и убедится в корректности подгружаемого class-файла.
Java stacktrace:
Exception in thread "main" java.lang.VerifyError: Expecting a stack map frame at branch target 10 at com.example.Main.main(Main.java:1)
- Пример ошибки при загрузке нативных библиотек. Как правило, самая частая причина такой ошибки - отсутствие библиотеки в Java library path'е (аргумент
-Djava.library.path=<library_path>
. Сам library path фактически является списком директорий и файлов, где JVM будет производить поиск нативных библиотек для их загрузки (своеобразный аналог Java classpath).Java stacktrace:Exception in thread "main" java.lang.UnsatisfiedLinkError: no nativeLib in java.library.path at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2447) at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:809) at com.example.NativeLoader.<clinit>(NativeWrapper.java:5) // <clinit>!
<clinit>
, это означает что ошибка произошла при инициализации класса, или в "статическом конструкторе", при инициализации полей и т.п. Так-же существует и<init>
, который обозначает конструктор класса. - Пример ошибки переполнения стека, как правило возникает когда случается бесконечная рекурсия, либо рекурсия достаточно продолжительная, что-бы забить стек. (При втором случае, можно обойтись расширением стека через аргумент
-Xss=4M
. Стандартный размер стека порядка 0.5-1мб).Java stacktrace:Exception in thread "main" java.lang.StackOverflowError at com.example.Recursive.call(Recursive.java:3) at com.example.Recursive.call(Recursive.java:3) ...
Пожалуйста, авторизуйтесь для просмотра ссылки.
:Почему за ошибку можно посчитать
NullPointerException
, а не XxxException
который случился раньше? Давайте представим, что XxxException
это ошибка подключения/соединения с базой данных (к примеру у нас отсутствует интернет соединение). Будет ли нормой то, что при отсутствии интернета наше приложение умирает? Я думаю что это не нормально. По этой причине проблема находится в коде указанном под ошибкой NullPointerException
, где отсутствует обработка исключений либо проверка на null
.Не стоит бояться ошибок и stacktrace'ов, они не страшные и как правило далеко не большие (если, конечно, вы не работаете в энтерпрайзе

Раздел 2. Краш-репорты и Minecraft
Crash-report Minecraft'а де-факто является тем-же stacktrace'ом, дополнительно украшенным информацией об системе, вашем устройстве и веселым "комментарием" разработчиков игры. Crash-report'ы в Minecraft практически всегда "многоуровневые"(имеют несколько ошибок в stacktrace'е), поэтому важно анализировать его весь, т.к. фактическая ошибка может быть где угодно. Поскольку это по большей части будут те-же stacktrace'ы, этот раздел будет больше про анализ ошибок которые можно встретить на этом форуме в разделе Minecraft'а, и пояснения как самостоятельно приходить к их решению.
Для начала давайте ознакомимся со структурой crash-report'а:
Crash-report:
---- Minecraft Crash Report ----
// This doesn't make any sense!
Time: 01.09.2025, 00:00
Description: Initializing game
---------------------------------------------------------------------------------------
-- Head --
Thread: Main
Stacktrace:
at org.example.MyClass.main(MyClass.java:5)
-- Initialization --
Details:
Stacktrace:
at org.example.MyClass.main(MyClass.java:5)
-- System Details --
Details:
Minecraft Version: 1.16.5
Minecraft Version ID: 1.16.5
Operating System: Windows 10 (amd64) version 10.0
Java Version: 22.0.1, Oracle Corporation
Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode, sharing), Oracle Corporation
Memory: 96420272 bytes (91 MB) / 199229440 bytes (190 MB) up to 3206545408 bytes (3058 MB)
...
В краш репорте есть вполне интересные блоки на которые можно обратить внимание, если наша проблема зависима от сборки JVM или комплектующих компьютера (к примеру не проявляется с видеокартами AMD Radeon, но проявляется на видеоадаптерах Intel Iris). Что-ж за они?
- Для начала, тот самый "веселый комментарий" от разработчиков игры. В зависимости от места где произошла ошибка внутри игры, описание будет рознится. Я думаю оно выступает сейчас скорее как традиция, т.к. подобные надписи в игре присутствуют уже более 10 лет.
Funny comment:
// This doesn't make any sense!
- Затем идут дата когда был записан crash-report и описание от самой игры на какой стадии случилась ошибка.
Timestamp:
Time: 01.09.2025, 00:00 Description: Initializing game
- И начинается самое интересное, идут 2 stacktrace'а. Первый - отвечающий за основную часть stacktrace'а и ошибки в определенном потоке (в данном случае - в основном потоке (Main), Второй - отвечающий за стартовую точку приложения.
Stacktrace:
-- Head -- Thread: Main Stacktrace: at org.example.MyClass.main(MyClass.java:5) -- Initialization -- Details: Stacktrace: at org.example.MyClass.main(MyClass.java:5)
- А в конце идёт системная информация, версия игры, Java, Java VM, информация об ядрах процессора, видеокарте, и прочем.
Код:
-- System Details -- Details: Minecraft Version: 1.16.5 Minecraft Version ID: 1.16.5 Operating System: Windows 10 (amd64) version 10.0 Java Version: 22.0.1, Oracle Corporation Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode, sharing), Oracle Corporation Memory: 96420272 bytes (91 MB) / 199229440 bytes (190 MB) up to 3206545408 bytes (3058 MB) ...
Как правило, crash-report'ов более чем достаточно для решения ошибки, но иногда случаются ошибки которые могут поломать механизм записи crash-report'ов. В таком случае необходимо открывать логи клиента/сервера и разбираться уже с ними, т.к. часто информация с crash-report'а дублируется и в логи, а если и нет - то как минимум сама ошибка там присутствовать обязана (если ваша ошибка не связана с крашем всей JVM).
Далее рассмотрим примеры ошибок и их решения. Рассматривать мы их будем в порядке начиная с самых простых, заканчивая более сложными.
- [Топик] Начнем с простого, отсутствие главного класса для запуска. Достаточно прочитать что нам написано в ошибке.
Код:
Error: Could not find or load main class net.minecraft.client.main.Main Caused by: java.lang.ClassNotFoundException: net.minecraft.client.main.Main
META-INF/MANIFEST.MF
, либо при запуске с указанием главного класса в обход манифеста. - Так-же существуют ошибки которые могут быть похожими на пример выше, однако могут иметь описание "Bad main class", либо класс может существовать но JVM отказывается его читать. В таком случае проблема может быть в нескольких местах:
- Jar файл(фактически zip-архив) повреждён
- Class файл повреждён
- Class файл не проходит проверку Security Manager из-за несовпадения хеш-сумм, описанных в файле
META-INF/MANIFEST.MF
для этого файла.
- [Топик] Ещё один довольно простой пример, тут у нас просто переполняется "куча"(Java Heap), в следствии чего у нас возникает ошибка
OutOfMemoryError
. Решение простое - дать приложению больше памяти через-Xmx=<MEM>
аргумент.Crash-report:---- Minecraft Crash Report ---- // You're mean. Time: 27.03.2025, 21:24 Description: Initializing game java.lang.OutOfMemoryError: Java heap space at java.desktop/java.awt.image.DataBufferInt.<init>(DataBufferInt.java:75) at java.desktop/java.awt.image.Raster.createPackedRaster(Raster.java:539) ...
- [Топик] Здесь - часто встречающаяся проблема при итерации по хеш-мапам, при итерации по хеш-мапам модифицировать её нельзя, вследствии чего у нас возникает
ConcurrentModificationException
. Решение включает в себя изменение стратегии итерации по мапе, либо использование concurrency-safe коллекции вродеConcurrentHashMap
.Пожалуйста, авторизуйтесь для просмотра ссылки..Java stacktrace:java.util.ConcurrentModificationException: null at java.util.HashMap$HashIterator.nextNode(HashMap.java:1597) ~[?:?] at java.util.HashMap$KeyIterator.next(HashMap.java:1620) ~[?:?] at java.lang.Iterable.forEach(Iterable.java:74) ~[?:?]
- [Топик] Простая проблема с
NullPointerException
, подобный пример мы рассматривали в разделе про stacktrace'ы. Что интересно, последний вызов происходит в функции самого Minecraft'а, из чего можно сделать предположение что здесь использовались Mixin'ы для инъекции кода в код майнкрафта. А так-же описание ошибки даёт понять, что скорее всего вызовAntiPush#isState()
производился через какое-то поле которое должно было хранить объект классаAntiPush
, но хранило оноnull
, в следствии чего собственно наша ошибка и была "выкинута" игрой.Crash-report:---- Minecraft Crash Report ---- // Don't do that. Time: 25.04.2025, 15:05 Description: Ticking player java.lang.NullPointerException: Cannot invoke "alpha.night.modules.impl.misc.AntiPush.isState()" because "antiPush" is null at net.minecraft.entity.player.PlayerEntity.isPushedByWater(PlayerEntity.java:1990) at net.minecraft.entity.Entity.handleFluidAcceleration(Entity.java:3273) at net.minecraft.entity.Entity.func_233567_aH_(Entity.java:1156) ...
- [Топик] Пример посложнее, crash-report без описания ошибки. Это уже поинтереснее, т.к. нам придётся заглядывать в код. Изначально мы видим что проблема у нас находится в классе
MsdfFont$Builder
, в функцииbuild(...)
, и сама ошибка происходит на строке 157. Отправляемся туда! Там-же видим что на 157 строке у нас происходит выброс ошибки по причине того, что полеdata
равноnull
. Если выбрасывается ошибка в таком случае, не сложно понять что полеdata
не должно бытьnull
. В нашем случае так-же достаточно посмотреть на описание ошибки в коде, которое даёт нам понять что коду "Не удалось прочитать файл с данными шрифта"(Failed to read font data file:...
). А значит пора бы убедится, всё ли в порядке у нас с файлом, существует ли он, и точно ли он такой, каким должен быть (поскольку читы, имхо, обычно довольно скудны на количество runtime-исключений в коде).Crash-report:---- Minecraft Crash Report ---- // This doesn't make any sense! Time: 13.03.2025, 18:36 Description: Initializing game --------------------------------------------------------------------------------------- -- Head -- Thread: Main Stacktrace: at org.excellent.client.utils.render.font.MsdfFont$Builder.build(MsdfFont.java:157) at org.excellent.client.utils.render.font.Font.create(Font.java:96) ...
Java code (MsdfFont$Builder#build(...)):public MsdfFont build() { FontData data = IOUtils.fromJsonToInstance(this.dataFile, FontData.class); Texture texture = IOUtils.toTexture(this.atlasFile); if (data == null) { throw new RuntimeException("Failed to read font data file: " + this.dataFile.toString() + "; Are you sure this is json file? Try to check the correctness of its syntax."); } ... }
- [Топик] Далее по списку у нас идёт crash-report с некорректным explicit-cast'ингом объектов и Gson'ом. В crash-report'е находим смотрим на первую-же строку stacktrace'а, идём сразу в файл разбираться почему у нас произошёл
ClassCastException
. Открыв код, мы видим что код написан глупо, поскольку никаких проверок на валидность объекта для cast'инга объектов попросту нету. Из-за этого, когдаJsonParser
возвращаетJsonNull
- всё ломается, потому-что мы этот объект пытаемся положить в поле с типомJsonObject
несмотря на то, что они не могут быть приведены к типам друг друга, из-за того что они оба наследуются только отJsonElement
. Решение - сделать проверку перед cast'ом объектов, да и всего-то.Crash-report:---- Minecraft Crash Report ---- // You're mean. Time: 10.03.2025, 17:14 Description: Initializing game java.lang.ClassCastException: class com.google.gson.JsonNull cannot be cast to class com.google.gson.JsonObject (com.google.gson.JsonNull and com.google.gson.JsonObject are in unnamed module of loader 'app') at eva.ware.config.ConfigStorage.loadConfiguration(ConfigStorage.java:72) at eva.ware.config.ConfigStorage.setupFolder(ConfigStorage.java:30)
Java code (ConfigStorage#loadConfiguration(...):public void loadConfiguration(String configuration) { Config config = findConfig(configuration); try { FileReader reader = new FileReader(config.getFile()); JsonParser parser = new JsonParser(); JsonObject object = (JsonObject) parser.parse(reader); // Нету проверки перед cast'ом config.loadConfig(object); } catch (FileNotFoundException e) { ... } catch (NullPointerException pointerException) { ... } // Нету catch-блока для ClassCastException для улавливания такого рода проблем }
- [Топик] Пришла пора задачек поинтереснее, где stacktrace вроде-бы подсказывает что не так, но решение может быть неочевидным. Такая задачка есть с чита Excellent Recode где используется конченая эвентная шина Пожалуйста, авторизуйтесь для просмотра ссылки., которая использует
LambdaFactory
в качестве 1 из механизмов диспетчеризации эвентов. И теперь внимание, самая распространенная проблема связанная с этим, появляется при... рефакторинге названий пакетов чита. Звучит ужасно, потому-что судя по всемуLambdaFactory
под капотом используют текстовые названия пакетов и т.п. Суть заключается в том, что в главном классе чита(org.excellent.client.Excellent
) есть функцияstart()
, которая и является проблемой, т.к. при переименовании всего чита, IDE не знает о том, что где-то естьString
который должен ориентироваться на название пакета, в следствии чего про это место много кто забывал, а после ничего и не работало из-за этого мягко-говоря странного механизма регистрации слушателей эвентов. Решение - нужно изменить значениеString
на актуальное название пакета.Crash-report:---- Minecraft Crash Report ---- // Don't do that. Time: 08.07.2025, 13:55 Description: Initializing game --------------------------------------------------------------------------------------- -- Head -- Thread: Main Stacktrace: at org.excellent.client.api.events.orbit.EventBus.getLambdaFactory(EventBus.java:257) at org.excellent.client.api.events.orbit.EventBus.getListeners(EventBus.java:234) at org.excellent.client.api.events.orbit.EventBus.getListeners(EventBus.java:223) at org.excellent.client.api.events.orbit.EventBus.lambda$getInstanceListeners$2(EventBus.java:218) at java.base/java.util.Map.computeIfAbsent(Map.java:1054) at java.base/java.util.Collections$SynchronizedMap.computeIfAbsent(Collections.java:2760) at org.excellent.client.api.events.orbit.EventBus.getInstanceListeners(EventBus.java:218) at org.excellent.client.api.events.orbit.EventBus.subscribe(EventBus.java:165) at org.excellent.client.api.events.Handler.<init>(Handler.java:8)
Java code (Excellent#start()):public void start() { eventHandler.registerLambdaFactory(devMode ? "org.excellent" : "exc", (lookupInMethod, klass) -> (MethodHandles.Lookup) lookupInMethod.invoke(null, klass, MethodHandles.lookup())); }
Раздел 3. JVM краш-логи
Пришло время самой тяжелой темы, которую даже я до сих пор особо не понимаю, но с которой мне приходится работать чуть ли не каждый день. JVM краш-логи (они-же файлы формата
hs_err_pid_XXXXX.log
). Файлы которые прочитать сложнее, которые появляются когда умирает вся JVM и как-то обработать эту ошибку внутри Java попросту не получится. Поэтому я попробую дать хотя-бы немного вводных на что можно обращать внимание при поиске решений, и разберем пару ситуации произошедших на форуме и в моей практике, но как обычно, для начала - структура:
JVM Crash log:
// Заголовок с "Сигнальной" ошибкой, проблемным фреймом и прочей информацией
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffdcf73ca03, pid=30616, tid=32784
#
# JRE version: Java(TM) SE Runtime Environment (17.0.11+7) (build 17.0.11+7-LTS-207)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (17.0.11+7-LTS-207, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, windows-amd64)
# Problematic frame:
# C [myNativeLibrary.dll+0x4ca03]
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# If you would like to submit a bug report, please visit:
# https://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
// Общая информация
--------------- S U M M A R Y ------------
// Командная строка с которой было запущено приложение
Command Line: -XX:+ShowCodeDetailsInExceptionMessages...
// Информация об процессоре, сборке ОС, времени запуска
Host: AMD Ryzen 7 7700 8-Core Processor , 16 cores, 63G, Windows 10 , 64 bit Build 19041 (10.0.19041.5915)
Time: Thu Jul 3 18:44:40 2025 RTZ 2 (s 10 , 64 bit Build 19041 (10.0.19041.5915) elapsed time: 1.897355 seconds (0d 0h 0m 1s)
// Информация об потоке
--------------- T H R E A D ---------------
Current thread (0x000001dcca6532c0): JavaThread "main" [_thread_in_native, id=32784, stack(0x000000c221a00000,0x000000c221b00000)]
Stack: [0x000000c221a00000,0x000000c221b00000], sp=0x000000c221afedd0, free space=1019k
// Нативные фреймы вне JVM
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [myNativeLibrary.dll.dll+0x4ca03]
// Фреймы внутри JVM
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j org.lwjgl.system.JNI.invokePC(JJ)S+0
j org.example.Main.doThatThing()V+16
v ~StubRoutines::call_stub
// "Сигнальная" ошибка
siginfo: EXCEPTION_ACCESS_VIOLATION (0xc0000005), reading address 0xffffffffffffffff
Registers:
RAX=0x007e0041004e0045, RBX=0x000001dd3c6136d8, RCX=0x00007ffdcfb0b038...
// Регистры указывающие на память чего-то
Register to memory mapping:
RIP=0x00007ffdcf73ca03 myNativeLibrary.dll
RAX=0x007e0041004e0045 is an unknown value
RBX={method} {0x000001dd3c6136e0} 'invokePC' '(JJ)S' in 'org/lwjgl/system/JNI'
...
// Дамп памяти стека
Top of Stack: (sp=0x000000c221afedd0)
0x000000c221afedd0: 00007ffdcfbad000 000001dd490eb3f0
...
// Информация об процессе, JVM и событиях внутри JVM
--------------- P R O C E S S ---------------
// Java потоки
Java Threads: ( => current thread )
=>0x000001dcca6532c0 JavaThread "main" [_thread_in_native, id=32784, stack(0x000000c221a00000,0x000000c221b00000)]
0x000001dcf7565030 JavaThread "Reference Handler" daemon [_thread_blocked, id=88892, stack(0x000000c222100000,0x000000c222200000)]
0x000001dcf7565bf0 JavaThread "Finalizer" daemon [_thread_blocked, id=89628, stack(0x000000c222200000,0x000000c222300000)]
0x000001dcfa47b7f0 JavaThread "Signal Dispatcher" daemon [_thread_blocked, id=88788, stack(0x000000c222300000,0x000000c222400000)]
0x000001dcfa47c3b0 JavaThread "Attach Listener" daemon [_thread_blocked, id=89976, stack(0x000000c222400000,0x000000c222500000)]
...
// JVM-Потоки (которыми владеет к примеру виртуальная машина)
Other Threads:
0x000001dcf7561590 VMThread "VM Thread" [stack: 0x000000c222000000,0x000000c222100000] [id=91604]
0x000001dcf73c1bc0 WatcherThread [stack: 0x000000c223200000,0x000000c223300000] [id=89868]
0x000001dcf73b0470 GCTaskThread "GC Thread#0" [stack: 0x000000c221b00000,0x000000c221c00000] [id=34836]
...
// Информация об "Куче"(Java Heap)
Heap:
garbage-first heap total 1040384K, used 4964K [0x000000040c800000, 0x0000000800000000)
region size 8192K, 2 young (16384K), 1 survivors (8192K)
Metaspace used 8093K, committed 8256K, reserved 1114112K
class space used 708K, committed 768K, reserved 1048576K
// Участки памяти "Кучи"(Java Heap)
Heap Regions: E=young(eden), S=young(survivor), O=old, HS=humongous(starts), HC=humongous(continues), CS=collection set, F=free, OA=open archive, CA=closed archive, TAMS=top-at-mark-start (previous, next)
...
// Данные использования памяти Metaspace(Java Metaspace)
Metaspace: ...
// Внутренняя статистика памяти
Internal statistics:
...
// Последние события JIT-компиляции
Compilation events (20 events): ...
// Прочие события касающиеся JIT и JVM
Deoptimization events (20 events): ...
Classes unloaded (0 events): ...
Classes redefined (0 events): ...
Internal exceptions (20 events): ...
VM Operations (14 events): ...
Events (20 events): ...
// Подключенные динамические библиотеки
Dynamic libraries:
0x00007ff61d300000 - 0x00007ff61d310000 C:\Program Files\Java\jdk-17\bin\javaw.exe
0x00007ffe16ef0000 - 0x00007ffe170e8000 C:\Windows\SYSTEM32\ntdll.dll
0x00007ffe156e0000 - 0x00007ffe157a2000 C:\Windows\System32\KERNEL32.DLL
0x00007ffe14720000 - 0x00007ffe14a16000 C:\Windows\System32\KERNELBASE.dll
// JVM аргументы использованные при запуске
VM Arguments:
jvm_args: -XX:+ShowCodeDetailsInExceptionMessages -agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:58991 -Dfile.encoding=UTF-8...
// Главный класс использованный для запуска
java_command: org.example.Main
// Java classpath
java_class_path (initial): ...
// Информация об системе
--------------- S Y S T E M ---------------
OS:
Windows 10 , 64 bit Build 19041 (10.0.19041.5915)
OS uptime: 3 days 15:01 hours
CPU: total 16 (initial active 16) (16 cores per cpu, 2 threads per core) family 25 model 97 stepping 2 microcode 0x0, cx8, cmov, fxsr, ht, mmx, 3dnowpref, sse, sse2, sse3, ssse3, sse4a, sse4.1, sse4.2, popcnt, lzcnt, tsc, tscinvbit, avx, avx2, aes, erms, clmul, bmi1, bmi2, adx, avx512f, avx512dq, avx512cd, avx512bw, avx512vl, sha, fma, vzeroupper, avx512_vpopcntdq, avx512_vpclmulqdq, avx512_vaes, avx512_vnni, clflush, clflushopt, avx512_vbmi2, avx512_vbmi
Memory: 4k page, system-wide physical 64730M (40013M free)
TotalPageFile size 103642M (AvailPageFile size 67833M)
current process WorkingSet (physical memory assigned to process): 266M, peak: 267M
current process commit charge ("private bytes"): 1429M, peak: 1430M
vm_info: Java HotSpot(TM) 64-Bit Server VM (17.0.11+7-LTS-207) for windows-amd64 JRE (17.0.11+7-LTS-207), built on Mar 11 2024 19:01:50 by "mach5one" with MS VC++ 17.6 (VS2022)
END.
Пожалуйста, авторизуйтесь для просмотра ссылки.
,
Пожалуйста, авторизуйтесь для просмотра ссылки.
.Нам интересно следующее:
JVM Crash log:
// Нативные фреймы вне JVM
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [myNativeLibrary.dll.dll+0x4ca03]
// Фреймы внутри JVM
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j org.lwjgl.system.JNI.invokePC(JJ)S+0
j org.example.Main.doThatThing()V+16
v ~StubRoutines::call_stub
- [Топик] Рассмотрим недавний пример, где по какой-то причине из-за нативной библиотеки умирала вся JVM. Первым делом получили JVM краш-лог, и смотрим что же там такое. На наше счастье там таки была подсказка которая вполне себе даёт понять что проблема очевидно на стороне нативной библиотеки (А именно siginfo - EXCEPTION_UNCAUGHT_CXX_EXCEPTION, что судя по названию даёт понять, что у нас есть неперехваченное исключение(ошибка), и что это произошло на стороне нативной библиотеки(_CXX_, то-же самое что и C++). Так-же сам краш-лог содержал инфу о нативной функции в которой произошла ошибка. Фактически решением в данной ситуации было бы дописать и пересобрать библиотеку да-бы при ошибках она просто возвращала
null
на стороне JVM, и проблема бы ушла, пусть иногда и возвращаяnull
как результат. (Почему SMTC(GlobalSystemMediaTransportControlsSessionManager#RequestAsync()
) иногда проваливается при закрытии приложении для меня загадка, мельком глядя в документации ничего не заметил).JVM Crash log:Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) C [KERNELBASE.dll+0xc9f0a] C [VCRUNTIME140.dll+0x6480] C [MediaPlayerInfo.dll+0x3c0e] Java frames: (J=compiled Java code, j=interpreted, Vv=VM code) J 30236 dev.redstones.mediaplayerinfo.impl.win.WindowsMediaPlayerInfo.getMediaSessions()Ljava/util/List; (0 bytes) @ 0x000001d54e841893 [0x000001d54e841840+0x0000000000000053] J 32720 c1 ru.mytheria.api.util.media.MediaPlayer.lambda$onTick$1()V (384 bytes) @ 0x000001d54925cea4 [0x000001d54925cd40+0x0000000000000164] J 32719 c1 ru.mytheria.api.util.media.MediaPlayer$$Lambda+0x000001d56083e3b8.run()V (8 bytes) @ 0x000001d54925c654 [0x000001d54925c5c0+0x0000000000000094] ... siginfo: EXCEPTION_UNCAUGHT_CXX_EXCEPTION (0xe06d7363), ExceptionInformation=0x0000000019930520 0x0000000ca7bfeab0 0x00007fff4b289b40 0x00007fff4b280000
C++ code:jobject Java_dev_redstones_mediaplayerinfo_impl_win_WindowsMediaPlayerInfo_getMediaSessions(JNIEnv* env, jobject obj) { ... // Вероятное место ошибки, фактически их несколько с Async-получением объекта. auto smtc = GlobalSystemMediaTransportControlsSessionManager::RequestAsync().get(); auto sessions = smtc.GetSessions(); ... }
Пожалуйста, авторизуйтесь для просмотра ссылки.иПожалуйста, авторизуйтесь для просмотра ссылки., можете ознакомится с разницей междуПожалуйста, авторизуйтесь для просмотра ссылки.и утечкой памяти по JVM референсам.
Заключение
Спасибо за прочтение.
На самом деле тема не то что-бы большая(если не брать в учёт JVM краш-логи), но примерами её можно раздувать бесконечно. Бояться исключений, ошибок, краш-репортов и краш-логов не нужно, это обычные вещи цель которых не дать случится ошибкам похлеще(вроде синего экрана, либо зависания намертво).
Если у вас есть какие-то интересные примеры stacktrace'ов, crash-report'ов или JVM краш-логов, не стесняйтесь ими делиться, самое интересное я добавлю в статью указав ваш тег!
Последнее редактирование: