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

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

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

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

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

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


person Erhannis    schedule 26.10.2018    source источник
comment
Надеюсь, вы понимаете, что нет никакой гарантии, что данный объект когда-либо будет удален сборщиком мусора.   -  person Bohemian♦    schedule 26.10.2018
comment
@Богемский Конечно. Но это нормально в моем случае использования, так как мне действительно нужно сериализовать вещи только в том случае, если у меня мало памяти, и в этом случае я считаю, что сборщик мусора более требователен к сборке мусора. Если это никогда не GCd, я могу просто вернуть никогда не сериализованный объект по запросу.   -  person Erhannis    schedule 26.10.2018
comment
Я думаю, вам, вероятно, потребуется по крайней мере переопределить пользовательский загрузчик классов и, возможно, потребуется изменить среду выполнения Java, чтобы поддерживать это.   -  person xuq01    schedule 26.10.2018
comment
найдите Phantom Reference и окончательный метод, вы найдете там свой ответ.   -  person akshaya pandey    schedule 26.10.2018
comment
Рассмотрите возможность использования WeakHashMap.   -  person Bohemian♦    schedule 26.10.2018
comment
@akshayapandey PhantomReference не позволяет вам получить референт вообще, а finalize — это метод, определенный для класса, выполняющего сборку мусора. Как говорится в вопросе, я не контролирую определения классов.   -  person Erhannis    schedule 26.10.2018
comment
@Bohemian WeakHashMap, я думаю, решает другую проблему - судя по моему чтению документа, это своего рода устройство для экономии памяти (первые два предложения этого класса предназначены в первую очередь....). Мой вариант использования заключается не в том, чтобы удалять объекты, которые я больше не использую, а в том, чтобы сериализовать объекты, когда они больше нигде не используются. Мне все еще нужны объекты. Если я не пропустил что-то важное, WeakHashMap просто молча отбрасывает записи, на чьи ключи больше нет ссылок; это не говорит вам, что они были.   -  person Erhannis    schedule 26.10.2018


Ответы (1)


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

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

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

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

person cruftex    schedule 26.10.2018