можно ли во время выполнения проверить, имеет ли объект прямую или косвенную ссылку на другой объект?
(я знаю, что могу использовать VisualVm или аналогичный для анализа HeapDump, но я хотел бы автоматизироватьво время выполнения)
Я работаю с WeakHashMap s, делаю что-то вроде этого:
public class MyClass {
// the Runnable will be eventually removed if the key is collected by the GC
private static final WeakHashMap<Object, Runnable> map = new WeakHashMap<>();
public static void main(String[] args) {
MyClass a = new MyClass(2);
MyClass b = new MyClass(20);
a = null;// no more Strong references to a
b = null;// no more Strong references to b
System.gc();
for (Runnable r : map.values()) {
r.run();
}
// will print (20), becouse using format() in the lambda cause a Strong
// reference to MyClass (b) and thus the WeakHashMap will never remove b
}
public MyClass(int i) {
if (i < 10) {
map.put(this, () -> {
System.out.println(i);
});
} else {
map.put(this, () -> {
// this is subtle, but calling format() create a strong reference
// between the Runnable and MyClass
System.out.println(format(i));
});
}
}
private String format(Integer i) {
return "(" + i + ")";
}
}
в коде два экземпляра MyClass добавят себя(как ключ) и запускаемый (как значение) для WeakHashMap.В первом случае (a
) Runnable просто вызывает System.out.println()
, и когда на экземпляр a больше нет ссылок (a = null
), запись будет удалена с карты.Во втором экземпляре (b
) Runnable также вызывает format()
функцию экземпляра MyClass.Это создаст строгую ссылку на b
, и добавление Runnable на карту приведет к условию блокировки, где значение является косвенной сильной ссылкой на ключ, предотвращающий сбор сборщиком мусора.
Теперь яЗнайте, чтобы избежать этих условий (например, используя Weakreference внутри лямбды), но это очень легко пропустить в реальном сценарии и приведет к утечке памяти.
Итак, перед добавлением пары вкарту, которую я хотел бы проверить, если значение каким-то образом ссылается на ключ, и, если так, вывести исключениеЭто было бы «отладочной» задачей и будет отключено в рабочей среде, поэтому мне все равно, будет ли она медленной или взломанной.
--- update ---
Iпытаюсь разобраться с WeakListeners и избежать их немедленного сбора, если на них не ссылаются.Поэтому я регистрирую их как notifier.addWeakListener(holder, e -> { ... });
, и это добавит слушателя в WeakHashMap, предотвращая его сбор до тех пор, пока держатель не будет активен.Но любая ссылка на держатель в слушателе создаст блокировку :(
Есть ли лучший способ?