Java BlackBerry 7:根进程中出现奇数内存泄漏

Java BlackBerry 7:根进程中出现奇数内存泄漏,java,blackberry,memory-leaks,persistence,Java,Blackberry,Memory Leaks,Persistence,我现在正在调查一个遗留BB7应用程序中的内存泄漏,该应用程序最初是由不再在该公司工作的开发人员为OS 4.5开发的。这个洞太大了,设备会随着时间的推移而退化,并在使用几个小时后使设备处于缓慢状态。它变慢了,因为可怕的黑色时钟在屏幕上以越来越高的频率出现在简单的操作中。我已经向调试器确认,当垃圾收集器启动时,会出现黑色时钟,并且在这些时间间隔内不会发生其他繁重的处理。显然,这些自动GC操作并不能解决内存不足的问题 我已经使用eclipse BB插件中的BlackBerry对象视图检查了流程应用程序

我现在正在调查一个遗留BB7应用程序中的内存泄漏,该应用程序最初是由不再在该公司工作的开发人员为OS 4.5开发的。这个洞太大了,设备会随着时间的推移而退化,并在使用几个小时后使设备处于缓慢状态。它变慢了,因为可怕的黑色时钟在屏幕上以越来越高的频率出现在简单的操作中。我已经向调试器确认,当垃圾收集器启动时,会出现黑色时钟,并且在这些时间间隔内不会发生其他繁重的处理。显然,这些自动GC操作并不能解决内存不足的问题

我已经使用eclipse BB插件中的BlackBerry对象视图检查了流程应用程序内存。在这个过程中,我没有看到任何类型的异常数量的实例。有趣的是,模型中的一个类的大量实例似乎都存在于根进程RAM中(pid=0),尽管它们是由这个应用程序进程创建的。它们似乎是由于在保存它们的持久性向量上进行迭代而泄漏的(例如:持久性存储中只有100个实例,但在对持久性向量进行几次迭代后,根进程RAM中有2000个实例。显然,额外的1900个实例是已经在持久性中的实例的克隆)。 启用调试器后,我可以看到实例一直堆积在RAM中,并且不会被控制台中看到的简短自动GC收集,但是当我手动从调试器强制GC时,它们会被删除(这需要相当长的时间才能运行)

主要的可疑对象是一个DAO类,它作为一个单例实例保存在
RuntimeStore
中(也必须从备用入口点调用)。它包含对保存在
PersistentStore
中的
BigVector
的引用,并包含上述模型类的实例。这是一个简短的版本:

    public class LeakyDAO { 
        private long persistentStoreId;
        private long runtimeStoreId;
        private PersistentObject persistentObject;
        private BigVector bigVector;

        private LeakyDAO(long id_p, long id_r) {
            persistentStoreId = id_p;
            runtimeStoreId = id_r;
            persistentObject = PersistentStore.getPersistentObject(persistentStoreId);
            Object o = persistentObject.getContents();      

            if(o instanceof BigVector){
                bigVector = (BigVector) o;
            } else {
                bigVector = new BigVector();
                persistentObject.setContents(bigVector);
            }       
        }

        public static synchronized LeakyDAO getInstance(long idPersist, long idRuntime) {
            RuntimeStore rs = RuntimeStore.getRuntimeStore();
            LeakyDAO dao = (LeakyDAO) rs.get(idRuntime);
            if (dao == null) {
                dao = new LeakyDAO(idPersist, idRuntime);
                try {
                    rs.put(idRuntime, dao);
                } catch (IllegalArgumentException e) {
                    //Already exists
                }
            }
            return dao;
        }

        public synchronized Object get(int index) {
            return ObjectGroup.expandGroup(bigVector.elementAt(index));
        }


        public synchronized void insertAt(int index, Persistable p) {       
            ObjectGroup.createGroupIgnoreTooBig(p);
            if (index >= bigVector.size()) {
                bigVector.addElement(p);
            } else {
                bigVector.insertElementAt(p, index);
            }
            persistentObject.setContents(bigVector);
            persistentObject.commit();
        }   
    }
我忽略的这门课有什么可怕的错误吗?此时,我还不能确认这些实例是否是问题的真正原因,因为当连接到调试器时,应用程序的行为非常不同。但是,是否可能由于操作系统中的错误(或已知行为),在反复调用
get
insertAt
后,某些实例被泄漏


更新

自动垃圾收集问题和一些OutOfMemoryErrors只有在调试器打开时才会出现。当它不处于调试模式时,自动GC会按预期工作,因此我认为调试器有问题。在“对象”视图中,我也进行了一些重置。

我看到每个“get”调用expandGroup,每个insert调用createGroup。我不认为这些函数试图提高效率。这意味着他们每次都复制对象,即使这不是必需的

使用这些对象的代码是否正在修改它们?或者,如果有修改,您是否可以缩小范围,让这些情况使用“getMutable”?
如果您可以执行上述任一操作,则可以从insertAt函数中删除'createGroup',从get函数中删除'expandGroup',并保存对象副本。

我看到每个'get'调用expandGroup,每个insert调用createGroup。我不认为这些函数试图提高效率。这意味着他们每次都复制对象,即使这不是必需的

使用这些对象的代码是否正在修改它们?或者,如果有修改,您是否可以缩小范围,让这些情况使用“getMutable”? 如果可以执行上述任一操作,则可以从insertAt函数中删除“createGroup”,从get函数中删除“expandGroup”,并保存对象副本