Java PrintCompilation output: что означают "сделанные не абитуриенты" и "сделанные зомби",
При запуске приложения Java 1.6 (1.6.0_03-b05) я добавил флаг -XX:+PrintCompilation
. На выходе для некоторых методов, в частности, некоторые из тех, которые, как мне известно, получаются много, я вижу текст made not entrant
и made zombie
.
Что это значит? Лучше всего предположить, что это шаг декомпиляции, прежде чем перекомпилировать этот метод или зависимость с большей оптимизацией. Это правда? Почему "зомби" и "абитуриент"?
Пример: довольно немного времени между некоторыми из этих строк:
[... near the beginning]
42 jsr166y.LinkedTransferQueue::xfer (294 bytes)
[... much later]
42 made not entrant jsr166y.LinkedTransferQueue::xfer (294 bytes)
--- n sun.misc.Unsafe::compareAndSwapObject
170 jsr166y.LinkedTransferQueue::xfer (294 bytes)
170 made not entrant jsr166y.LinkedTransferQueue::xfer (294 bytes)
4% jsr166y.LinkedTransferQueue::xfer @ 29 (294 bytes)
171 jsr166y.LinkedTransferQueue::xfer (294 bytes)
[... even later]
42 made zombie jsr166y.LinkedTransferQueue::xfer (294 bytes)
170 made zombie jsr166y.LinkedTransferQueue::xfer (294 bytes)
171 made not entrant jsr166y.LinkedTransferQueue::xfer (294 bytes)
172 jsr166y.LinkedTransferQueue::xfer (294 bytes)
[... no further logs]
Ответы
Ответ 1
Я собрал некоторую информацию об этом на моем блоге. Клифф Нажмите комментарий, который я нашел, говорит:
Зомби-методы - это методы, чей код был недопустим при загрузке классов. Как правило, серверный компилятор делает агрессивные вложения решений не конечных методов. До тех пор, пока встроенный метод никогда не будет переопределен, код будет правильным. Когда подкласс загружается и метод переопределяется, скомпилированный код прерывается для всех будущих вызовов. Код объявляется "не входящим" (нет будущих абонентов для разбитого кода), но иногда существующие абоненты могут продолжать использовать код. В случае вложения, это недостаточно хорошо; существующие стеки кадров вызывающих абонентов "деоптимизируются", когда они возвращаются к коду из вложенных вызовов (или просто если они выполняются в коде). Когда больше кадров стека не помещают ПК в сломанный код, он объявляет "зомби" - готов к удалению после того, как GC приблизится к нему.
Ответ 2
Это абсолютно не область экспертизы для меня, но мне было интересно, и так было немного копать.
Несколько ссылок, которые могут вам показаться интересными: OpenJDK: nmethod.cpp, OpenJDK:. nmethod.hpp
Выдержка из nmethod.hpp
:
// Make the nmethod non entrant. The nmethod will continue to be
// alive. It is used when an uncommon trap happens. Returns true
// if this thread changed the state of the nmethod or false if
// another thread performed the transition.
bool make_not_entrant() { return make_not_entrant_or_zombie(not_entrant); }
//...
Как начальное место.
Ответ 3
Вот это Gist с невероятным количеством информации на PrintCompilation
. В частности, он говорит:
Когда происходит деоптимизация, если принято решение о признании недействительным оскорбительного nmethod
, оно сначала будет "сделанным не первым"; и затем, когда NMethodSweeper
обнаруживает, что никаких активировок на стеках уже нет, он "сделан зомби";