【问题标题】:Eclipse heap walkEclipse 堆遍历
【发布时间】:2011-03-28 12:12:15
【问题描述】:

在调试 Java 代码时,Eclipse 有一个特性,允许它查找给定类型的所有实例(通过变量窗口中的上下文菜单)。有没有办法以编程方式过滤这些?例如,我想要类 FieldInstruction 的所有实例,其中

the_instance.getType().getName().equals("somestring")  

评估为真。

当我试图调试 已经 应该枚举所有实例的代码时,只是创建我自己的代码来遍历类存在的树结构有点违背了目的。我真的很希望能够通过“显示”或“表达式”窗口进行此过滤。

【问题讨论】:

    标签: eclipse debugging heap-memory


    【解决方案1】:

    我最终创建了一个相当老套的“InstanceRegistry”类。在我要跟踪的每个类类型的构造函数中,我放了

    InstanceRegistry.register(this);
    

    这甚至负责在所有超类和接口下“注册”实例。

    迭代实例(甚至可以在 Eclipse 显示窗口中完成):

    for(Object instance : InstanceRegistry.getInstances(FieldInstruction.class)) {
        //do something
    }
    

    InstanceRegistry类的源码:

    import java.lang.ref.WeakReference;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Iterator;
    
    public class InstanceRegistry {
        private InstanceRegistry() {}
    
        private static HashMap<Class<?>, HashSet<WeakReference<?>>> instances = new HashMap<Class<?>, HashSet<WeakReference<?>>>();
    
        public static <T> Iterable<T> getInstances(final Class<T> type) {
            return new Iterable<T>() {
                public Iterator<T> iterator() {
                    return new Iterator<T>() {
                        Iterator<WeakReference<?>> it = instances.get(type).iterator();
                        T item = find();
    
                        {
                            System.gc();
                        }
    
                        public boolean hasNext() {
                            return item != null;
                        }
    
                        private T find() {
                            WeakReference<T> fi;
                            while(it.hasNext()) {
                                fi = (WeakReference<T>) it.next();
                                if(fi.get() != null)
                                    return fi.get();
                            }
                            return null;
                        }
    
                        public T next() {
                            T ret = item;
                            item = find();
                            return ret;
                        }
    
                        public void remove() {
                            throw new UnsupportedOperationException();
                        }
                    };
                }
            };
        }
    
        private static void put(Class<?> type, WeakReference<?> instance) {
            HashSet<WeakReference<?>> list = instances.get(type);
            if(list == null) {
                list = new HashSet<WeakReference<?>>();
                instances.put(type, list);
            }
            list.add(instance);
        }
    
        public static void register(Object instance) {
            WeakReference<Object> inst = new WeakReference<Object>(instance);
            Class<?> c = instance.getClass();
            do {
                put(c, inst);
                for(Class<?> ci : c.getInterfaces()) {
                    put(ci, inst);
                }
                c = c.getSuperclass();
            } while(c != Object.class);
        }
    }
    

    【讨论】:

    • 此解决方案与仅将所有实例添加到集合有什么区别?
    • 真的吗?非常有限。主要是为了方便静态方法、gc 调用等。老实说,我当时只用过一次,从那以后就再也没有——所以结果证明它没有那么有用。
    猜你喜欢
    • 2016-08-13
    • 2011-12-17
    • 1970-01-01
    • 1970-01-01
    • 2014-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-12
    相关资源
    最近更新 更多