Прямая память Java: использование sun.misc.Cleaner в пользовательских классах
В Java память, выделяемая прямыми буферами nio, освобождается экземплярами sun.misc.Cleaner, некоторые специальные phantom ссылки, которые более эффективны, чем завершение объекта.
Является ли этот механизм очистки жестко закодированным в JVM только для подклассов прямого буфера или можно также использовать очистители в пользовательских компонентах (например, для записи собственного прямого байтового буфера)?
Здесь я не говорю о том, чтобы извлечь поле чистого существующего nio-прямого буфера. Я не говорю о том, чтобы вручную освободить память. Речь идет о написании нового класса, который выделяет прямую память и эффективно и автоматически очищается механизмом сбора мусора.
Ответы
Ответ 1
Потратив больше времени на чтение документа API (http://docs.oracle.com/javase/7/docs/api/java/lang/ref/package-summary.html), я думаю, у меня есть более подробный ответ:
1) можно повторно использовать sun.misc.Cleaner для эффективной очистки ваших собственных пользовательских классов. Вы объявляете уборщика, вызвав предоставленный метод factory:
sun.misc.Cleaner.create(Object ob, Runnable cleanup);
В течение некоторого времени я не мог заставить его работать правильно, потому что я был достаточно глуп, чтобы определить исполняемый код очистки моего чище как анонимного класса, который содержал (сильную) ссылку на мой объект референта, когда-либо "phantom достижимый"...
2) Нет другого способа реализовать такую эффективную очистку (даже с помощью ссылок phantom)
В действительности поток обработчика ссылок обрабатывает экземпляры sun.misc.Cleaner особым образом:
// Fast path for cleaners
if (r instanceof Cleaner) {
((Cleaner)r).clean();
continue;
}
Это означает, что код очистки вызывается непосредственно из потока обработчика ссылок, а при стандартном использовании ссылки должны быть выделены потоком обработчика ссылок, а затем удалены и обработаны другим потоком приложения.
Ответ 2
Если вы полагаетесь на что-либо в пакете sun.misc
, вы рискуете исчезнуть и сломать свой код. Некоторые части более стабильны, чем другие, но часто это плохая идея (devil advocate: многие методы в sun.misc.Unsafe
на самом деле реализованы с помощью JVM intrinsics, что делает их быстрее, чем написанный пользователем JNI-код).
В этом случае я думаю, что это плохая идея: Cleaner
- одна из возможных реализаций очистки через PhantomReference
. Есть и другие; Google для примеров. В этом случае вы можете посмотреть исходный код самого Cleaner
в качестве примера того, как использовать ссылки phantom.
Вам понадобится какой-то обработчик очистки, если у вас будут объекты на куче, которые относятся к объектам без кучи. В противном случае вы создадите утечку истинной памяти, когда эти объекты на кучи будут собраны.