Как реализовать явную маркировку некоторых ссылок как "ненужных" в 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. Я думаю, это то, что вы ищете

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