Выполните обратный вызов для объекта java только перед сборкой мусора

Предыстория: Значит, у меня была отличная идея, не так ли? Иногда вы собираете огромное количество данных, и вам не нужно постоянно получать к ним доступ, но они могут вам и не понадобиться после завершения программы, и вы действительно не хотите возиться с таблицы базы данных и т. д. Что, если бы у вас была библиотека, которая молча и автоматически сериализует объекты на диск, когда вы их не используете, и молча возвращает их, когда они вам нужны? Итак, я начал писать библиотеку; у него есть несколько коллекций, таких как «DiskList» или «DiskMap», куда вы помещаете свои объекты. Они хранят ваши объекты через WeakReferences. Пока вы все еще используете данный объект, у него есть сильные ссылки на него, поэтому он остается в памяти. Когда вы прекращаете его использовать, объект собирается сборщиком мусора, и непосредственно перед этим сборка сериализует его на диск (*). Когда вам снова нужен объект, вы запрашиваете его по индексу или ключу, как обычно, и коллекция десериализует его (или возвращает его из своего внутреннего кеша, если он еще не был GCd).

(*) Смотрите, это точка преткновения. Для того, чтобы это сработало, мне нужно иметь возможность получать уведомление ТОЛЬКО ДО того, как объект станет GCd - после того, как на него больше не будет ссылок (и, следовательно, объект больше не может быть изменен), но до того, как объект будет удален из памяти. Это оказывается трудным. Я на мгновение подумал, что использование ReferenceQueue спасет меня, но, увы, он возвращает ссылку, референт которой до сих пор всегда был нулевым.

Есть ли способ, получив произвольный объект, получить (через обратный вызов или очередь и т. д.) Объект после того, как он будет готов к сборке мусора, но до того, как он будет собран?

Я знаю, что (Object).finalize() в принципе может это делать, но мне придется иметь дело с классами, которые мне не принадлежат, и чьи методы finalize я не могу законно переопределить. Я бы предпочел не так загадочно, как пользовательские загрузчики классов, манипуляции с байт-кодом или отражение, но я сделаю это, если понадобится.

(Кроме того, если вы знаете о существующих библиотеках, которые выполняют прозрачное кэширование диска, я бы отнесся к этому положительно, хотя мои требования к такой библиотеке были бы довольно строгими.)

Надеюсь, вы понимаете, что нет никакой гарантии, что данный объект Когда-либо будет удален сборщиком мусора.

Bohemian 26.10.2018 06:33

@ Богемный Конечно. Но в моем случае это нормально, поскольку мне действительно нужно сериализовать вещи только в том случае, если у меня мало памяти, и в этом случае я считаю, что сборщик мусора более требователен к сборке мусора. Если это никогда не GCd, я могу просто вернуть никогда не сериализованный объект по запросу.

Erhannis 26.10.2018 06:35

Я думаю, вам, вероятно, потребуется хотя бы переопределить загрузчик пользовательских классов и, возможно, потребуется изменить среду выполнения Java для поддержки этого.

xuq01 26.10.2018 06:36

найдите Phantom Reference и последний метод, вы найдете там свой ответ.

akshaya pandey 26.10.2018 06:37

Рассмотрите возможность использования WeakHashMap.

Bohemian 26.10.2018 06:50

@akshayapandey PhantomReference не позволяет получить референт вообще, а finalize - это метод, определенный для класса, собирающего мусор. Как говорится в вопросе, у меня нет контроля над определениями классов.

Erhannis 26.10.2018 08:46

@Bohemian WeakHashMap решает другую проблему, я думаю - судя по моему чтению документа, это своего рода устройство для экономии памяти (первые два предложения «Этот класс предназначен в первую очередь ....»). Мой вариант использования не для удаления объектов, которые я больше не использую, а для сериализации объектов, когда они больше нигде не используются. Мне все еще нужны предметы. Если я не упустил из виду что-то важное, WeakHashMap просто молча отбрасывает записи, ключи которых больше не упоминаются; это не говорит вам, кем они были.

Erhannis 26.10.2018 08:52
0
7
330
1

Ответы 1

Вы можете найти кеш, который поддерживает «кэширование с обратной записью» и многоуровневое хранение. Известными продуктами будут EHCache, Hazelcast, Infinispan.

Или вы можете создать что-то самостоятельно с кешем и временем простоя до истечения срока. Тогда доступ к кешу будет «использованием» объекта.

Is there a way, having been given an arbitrary object, to receive (via callback or queue, etc.) the object after it is ready to be garbage collected, but before it IS garbage collected?

Это сильно мешает сборке мусора. Скорее всего, это приведет к остановке вашего приложения или всей системы. Что вы хотите сделать, так это запустить дисковый ввод-вывод и потенциально выделить дополнительные объекты, когда в системе мало или не хватает памяти. Если вам удастся это сработать, вы в конечном итоге будете использовать больше кучи, чем раньше, поскольку кучу всегда нужно расширять, когда срабатывает сборщик мусора.

Другие вопросы по теме