我正在与垃圾收集器挣扎。我想列出所有可以从某个对象强或弱地到达的对象。我知道我需要递归地做,但我找不到一种简单的方法来实现它。请你帮助我好吗?
public static List<Object> getAllReachableObjects (Object from)
答案 0 :(得分:1)
直接的解决方案不应该那么困难,但是......请注意,可以从给定对象到达许多对象....
根据评论编辑:
物体应分为柔软,弱,幻影和强烈可达的物体。这有点复杂。可以手动实现基于图形的优雅解决方案,但我从第一个答案中实际修改了代码。请注意,这尚未经过广泛测试。
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
public class AllReachableObjects
{
public static void main(String[] args)
{
TestObject a = new TestObject("a", null, null, null, null);
TestObject as = new TestObject("as", a, null, null, null);
TestObject aw = new TestObject("aw", null, a, null, null);
TestObject ap = new TestObject("ap", null, null, a, null);
TestObject ar = new TestObject("ar", null, null, null, a);
printInfo(new ReachableObjects(as));
printInfo(new ReachableObjects(aw));
printInfo(new ReachableObjects(ap));
printInfo(new ReachableObjects(ar));
TestObject asr = new TestObject("as", null, null, null, as);
TestObject ars = new TestObject("as", ar, null, null, null);
printInfo(new ReachableObjects(asr));
printInfo(new ReachableObjects(ars));
}
private static void printInfo(ReachableObjects r)
{
System.out.println("Soft");
printList(r.getSoftlyReachable());
System.out.println("Weak");
printList(r.getWeaklyReachable());
System.out.println("Phantom");
printList(r.getPhantomReachable());
System.out.println("Strong");
printList(r.getStronglyReachable());
}
private static void printList(List<Object> list)
{
for (Object object : list)
{
System.out.println(" "+object+" (class "+object.getClass()+")");
}
}
}
class ReachableObjects
{
private static final Field REFERENCE_REFERENT_FIELD =
initReferenceReferentField();
private static Field initReferenceReferentField()
{
try
{
return Reference.class.getDeclaredField("referent");
}
catch (NoSuchFieldException e)
{
e.printStackTrace();
}
catch (SecurityException e)
{
e.printStackTrace();
}
return null;
}
private Set<Object> softlyReachable;
private Set<Object> weaklyReachable;
private Set<Object> phantomReachable;
private Set<Object> stronglyReachable;
public ReachableObjects(Object object)
{
softlyReachable = new LinkedHashSet<Object>();
weaklyReachable = new LinkedHashSet<Object>();
phantomReachable = new LinkedHashSet<Object>();
stronglyReachable = new LinkedHashSet<Object>();
try
{
collectAllReachableObjects(object, stronglyReachable, "");
}
catch (IllegalArgumentException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
softlyReachable.removeAll(weaklyReachable);
softlyReachable.removeAll(phantomReachable);
softlyReachable.removeAll(stronglyReachable);
weaklyReachable.removeAll(softlyReachable);
weaklyReachable.removeAll(phantomReachable);
weaklyReachable.removeAll(stronglyReachable);
phantomReachable.removeAll(softlyReachable);
phantomReachable.removeAll(weaklyReachable);
phantomReachable.removeAll(stronglyReachable);
}
private void collectAllReachableObjects(
Object from, Set<Object> result, String indent)
throws IllegalArgumentException, IllegalAccessException
{
if (result.contains(from))
{
return;
}
result.add(from);
Class<?> c = from.getClass();
Class<?> leafClass = c;
while (c != null)
{
//System.out.println(indent+"Class "+c);
Field fields[] = c.getDeclaredFields();
for (Field field : fields)
{
//System.out.println(indent+"Field "+field+" of "+c);
if (Modifier.isStatic(field.getModifiers()))
{
continue;
}
boolean wasAccessible = field.isAccessible();
field.setAccessible(true);
Object value = field.get(from);
if (value != null)
{
Set<Object> nextResult = stronglyReachable;
if (field.equals(REFERENCE_REFERENT_FIELD))
{
if (leafClass.equals(SoftReference.class))
{
nextResult = softlyReachable;
}
else if (leafClass.equals(WeakReference.class))
{
nextResult = weaklyReachable;
}
else if (leafClass.equals(PhantomReference.class))
{
nextResult = phantomReachable;
}
}
collectAllReachableObjects(value, nextResult, indent+" ");
}
field.setAccessible(wasAccessible);
}
c = c.getSuperclass();
}
}
List<Object> getSoftlyReachable()
{
return new ArrayList<Object>(softlyReachable);
}
List<Object> getWeaklyReachable()
{
return new ArrayList<Object>(weaklyReachable);
}
List<Object> getPhantomReachable()
{
return new ArrayList<Object>(phantomReachable);
}
List<Object> getStronglyReachable()
{
return new ArrayList<Object>(stronglyReachable);
}
}
class TestObject
{
String name;
SoftReference<TestObject> softReference;
WeakReference<TestObject> weakReference;
PhantomReference<TestObject> phantomReference;
Object strongReference;
TestObject(String name,
TestObject soft, TestObject weak, TestObject phantom, TestObject strong)
{
this.name = name;
if (soft != null)
{
softReference = new SoftReference<TestObject>(soft);
}
if (weak != null)
{
weakReference = new WeakReference<TestObject>(weak);
}
if (phantom != null)
{
phantomReference = new PhantomReference<TestObject>(phantom, new ReferenceQueue<>());
}
strongReference = strong;
}
@Override
public String toString()
{
return name;
}
}
答案 1 :(得分:1)
不幸的是,这并没有真正起作用。好的,我只想拥有这样的方法:
public static List < Object > getStronglyReachable (Object from)
// contains all objects that are ONLY strongly reachable
public static List < Object > getSoftlyReachable (Object from)
// contains all objects that are strongly OR softly reachable
public static List < Object > getWeaklyReachable (Object from)
// contains all objects that are strongly OR softly OR weakly reachable
请记住,对象可以是数组。代码需要类似:
// if an object is an array, iterate over its elements
if (from.getClass ().isArray ())
for (int i = 0; i < Array.getLength (from); i++)
collectAllReachableObjects (Array.get (from, i), result);