Можем ли мы отключить финализаторы?
Поскольку существует небольшая гарантия того, когда и даже если финализаторы запускаются, а финализаторы в настоящее время считаются запахом, - есть ли способ убедить JVM полностью пропустить все процессы финализации?
Я прошу, потому что у нас есть приложение с мамонтом, которое при переходе на новую JVM (не уверен, что на этом этапе) оказывается на коленях тем, что очень похоже на известные проблемы с финализаторами (исключение выбрано и, следовательно, очень медленный GC).
Добавлен
Существует некоторая дискуссия по Устранение проблемы утечки Java-памяти: финализация?, где предполагается, что основная проблема возникает, когда исключения исключаются из финализаторов, поскольку это замедляет процесс окончательной доработки.
Моя проблема проявляется в резком замедлении, когда память становится низкой, а анализ дампов кучи показывает большое количество объектов Finalizer
(более 10 000 000), что указывает на то, что замедление может быть их ошибкой, поскольку они задерживают GC. Очевидно, я ошибаюсь.
У меня нет возможности требовать рефакторинга.
Ответы
Ответ 1
Есть ли способ убедить JVM полностью пропустить все процессы финализации?
Словом Нет.
Но если большая часть ваших объектов имеет методы finalize
и/или методы finalize
, особенно дороги, я думаю, что они вряд ли сделают GC "очень медленным". Я ожидаю, что проблема в другом.
Я предлагаю вам включить GC-журнал, чтобы попытаться получить более полное представление о том, что на самом деле происходит.
Но я также согласен, что рефакторинг кода, чтобы избавиться от методов finalize()
, вероятно, будет хорошим в долгосрочной перспективе. (Очень мало ситуаций, когда использование finalize
действительно является лучшим решением.)
ОБНОВЛЕНИЕ - ваши новые доказательства довольно убедительные, хотя и не доказательство!.
У меня нет возможности требовать рефакторинга.
Затем я предлагаю вам поставить доказательства у ног людей, которые делают: -).
В качестве альтернативы вы можете добавить обработчик исключений для подозрительных методов finalize
, чтобы узнать, выбрасывают ли они исключения. (И если они есть, то измените их, чтобы исключить исключения...)
Но суть в том, что если финализация является реальной причиной ваших проблем с производительностью, лучший (и, вероятно, единственный) способ их исправить - это изменить код.
Ответ 2
Это , чтобы подавить финализацию на определенных объектах. Он не требует обработки байт-кода, как заметил один комментатор.
Процедура описана здесь и предоставляется исходный код. Класс java.lang.ref.Finalizer
отвечает за ведение списка объектов, которые еще не были доработаны. Чтобы подавить завершение ваших интересующих объектов, достаточно использовать API-интерфейсы отражения, чтобы получить блокировку в поле lock
, перебрать связанный список unfinalized
, который поддерживает класс Finalizer, и удалить ваш объект из этого списка.
Я пробовал этот метод для безопасного создания пользовательских сериализованных объектов, минуя вызов конструктора и избегая проблем, когда финализатор будет вызываться с обычным GC. Перед применением этого метода моя JVM будет ломаться с жесткими ошибками в потоке финализатора; поскольку применение этого метода не происходит.
Ответ 3
Вы не можете отключить finalizer
в java, но все, что вы можете сделать, это написать код, который облегчит GC: -).