Как реализовать явную маркировку некоторых ссылок как "ненужных" в Java?
Мне кажется, что я обнаружил ситуацию, когда стандартный алгоритм сборки мусора не может быть хорошо использован.
Предположим, у меня есть какой-то объект A
, который добавляет себя в качестве прослушивателя событий для объекта B
на строительстве. Поскольку объект имеет все необходимые данные, чтобы добавить себя в качестве слушателя, следовательно, он также имеет данные для удаления себя из слушателей.
К сожалению, процесс удаления не может быть инициирован GC
, потому что объект будет указан в списке слушателей, пока не будет явно удален.
Таким образом, это означает, что либо объект никогда не должен добавлять себя в качестве слушателя, либо должен быть способ пометить некоторые ссылки как неважные. В последнем случае GC
будет инициировать сборку мусора, даже если существуют некоторые ссылки на объект - если они имеют только "неважный" случай.
Очевидно, программист должен быть обязан очистить все неважные ссылки в некотором методе, например dispose
или же finalize
,
Я понимаю, что это прямое внедрение будет отбеливателем безопасности. Например, если программист нарушил удаление контракта, сборщик мусора предоставит неверные ссылки.
Итак, вопрос в том, есть ли какая-нибудь библиотека или шаблон для реализации этих отношений?
3 ответа
Если вы просто хотите, чтобы время жизни вашего объекта управлялось ссылками на него, а не как на слушателя, вы можете изменить свою коллекцию слушателей на " Слабую " коллекцию, такую как WeakHashMap. Такая коллекция использует Weak References, чтобы избежать сохранения объектов после очистки всех других ссылок.
В общем, вы должны сделать своей задачей удаление ссылок, когда вы хотите, чтобы объект собирал мусор. Это часть управления памятью в среде сбора мусора.
Просто, например:
class MyInternalFrame extends JInternalFrame implements ActionListener {
...
void removeSelfAndDispose() {
for(JMenuItem button : parent.getMenuItems())
button.removeActionListener(this);
dispose();
}
}
Однако на самом деле лучше избегать хранения этих постоянных ссылок. Например, используйте static
вложенные классы вместо реализации слушателя в контейнере.
Можно было бы использовать WeakReference
придумать слушателя, который не мешает сборке мусора, например:
class MyInternalFrame extends JInternalFrame {
...
MyInternalFrame() {
for(JMenuItem button : parent.getMenuItems())
button.addActionListener(new WeakListener(this, button));
}
static class WeakListener implements ActionListener {
final Reference<JInternalFrame> ref;
final AbstractButton button;
WeakListener(JInternalFrame frame, AbstractButton button) {
ref = new WeakReference<JInternalFrame>(frame);
this.button = button;
}
@Override
public void actionPerformed(ActionEvent ae) {
JInternalFrame frame = ref.get();
if(frame == null) {
button.removeActionListener(this);
return;
}
...
}
}
}
Но это отрывочно и на него нельзя полагаться. Мы не контролируем, когда запускается сборка мусора, поэтому подобное может привести к непредсказуемому поведению. (Объект, на который мы сохраняем ссылку, все еще существует и реагирует на события после того, как вы думаете, что он был удален.)
Более надежно просто предотвращать размещение нежелательных ссылок или умышленно удалять их, когда это уместно.
Проверьте различные подклассы ссылки в Java. Я думаю, это то, что вы ищете