我正在编写一个可以产生大量垃圾的应用程序,但远远不足以达到内存限制。也就是说,即使产生垃圾,也不需要收集垃圾。但是,尽管如此,尽管使用了可用内存总量的很小一部分,垃圾收集器仍然被调用并且滞后于我的应用程序。
从这个输出中可以看出,我只使用了2%的可用内存,但垃圾收集器一直在运行:
12-22 04:36:08.219: D/dalvikvm(12033): WAIT_FOR_CONCURRENT_GC blocked 61ms
12-22 04:36:08.359: D/dalvikvm(12033): GC_CONCURRENT freed 1012K, 98% free 11865K/405196K, paused 4ms+13ms, total 73ms
12-22 04:36:08.359: D/dalvikvm(12033): WAIT_FOR_CONCURRENT_GC blocked 38ms
12-22 04:36:08.479: D/dalvikvm(12033): GC_CONCURRENT freed 1020K, 98% free 11862K/405196K, paused 3ms+13ms, total 66ms
12-22 04:36:08.479: D/dalvikvm(12033): WAIT_FOR_CONCURRENT_GC blocked 36ms
12-22 04:36:08.649: D/dalvikvm(12033): GC_CONCURRENT freed 1015K, 98% free 11863K/405196K, paused 2ms+16ms, total 78ms
12-22 04:36:08.649: D/dalvikvm(12033): WAIT_FOR_CONCURRENT_GC blocked 66ms
12-22 04:36:08.789: D/dalvikvm(12033): GC_CONCURRENT freed 1017K, 98% free 11861K/405196K, paused 2ms+13ms, total 66ms
12-22 04:36:08.789: D/dalvikvm(12033): WAIT_FOR_CONCURRENT_GC blocked 58ms
完全避免这种不必要的垃圾收集会破坏我的应用程序。
如果我有足够的可用内存,为什么垃圾收集器会运行?有什么办法可以让垃圾收集器运行直到绝对必要吗?我还要提一下,我正在使用root手机。
谢谢!
编辑: 呃..我一直在尝试使用工厂和各种技术消除所有垃圾,但仍然有相当数量的生成,我认为这是由于s1 + s2 + s3形式的一些字符串连接。我已将这些表达式转换为可以保存对每个组件的引用的表单,但我不确定它是否是气密的。您是否看到以下行生成了垃圾?
String ss1 = input.substring(m, m+k1);
String ss2 = ss1 + possible_perturbations1.charAt(p1);
String ss3 = input.substring(m+k1+1, m+k2);
String ss4 = ss2 + ss3;
String ss5 = ss4 + possible_perturbations2.charAt(p2);
String ss6 = input.substring(m+k2+1, m+i+1);
String current_str = ss5 + ss6;
allStrs.add(ss1);
allStrs.add(ss2);
allStrs.add(ss3);
allStrs.add(ss4);
allStrs.add(ss5);
allStrs.add(ss6);
allStrs.add(current_str);
一些注意事项:大多数标准库容器的remove函数会产生垃圾,生成临时变量(如字符串,整数,双打等)的对象之间的大多数二进制操作也是如此...我猜,大多数情况下,但仍然很清楚。
答案 0 :(得分:3)
没有你的代码,不容易说,为什么要调用垃圾收集器,它不是错误,但是如果它们是空闲的,它的职责是收集内存块。
当您拥有已创建且不再使用的对象时,垃圾收集器将激活。
不被GC滞后的最好方法是避免一直收集垃圾。例如,您可以重用对象,而不是将它们归零并创建新对象。
但是,仅供参考,你不能阻止垃圾收集器运行,甚至不尝试。
答案 1 :(得分:0)
即使应用程序仅使用一小部分可用堆内存,Android的GC也会正常运行。
一个可能的原因是:GC运行的时间长达几毫秒,比GC运行的几秒钟长(用户会注意到这一点)。
你是如何制造垃圾的?在大多数情况下,您只需创建固定数量的对象并重复使用它们(可能通过对象池)。
如果您100%确定自己知道自己在做什么并且没有更好的解决方案,则可以保留对垃圾对象的引用,以防止GC删除它们。但你几乎肯定不想这样做。
<强>更新强>
通常,你应该避免String连接(每个concat创建新对象)并改为使用StringBuilder:
String abc = a + b + c; // Wrong
String abc = new StringBuilder(a).append(b).append(c).toString(); // Right
答案 2 :(得分:0)
垃圾收集器会随时运行。没有办法阻止垃圾收集器。甚至没有真正的方法来调用垃圾收集器,你只询问垃圾收集器是否会运行,但即使这样,它也有可能无法运行。
垃圾收集器不仅会在内存不足时运行,它总是会尝试阻止“OutOfMemory”异常。据我所知,GC将按给定的时间间隔运行,并查看范围内不再需要的变量。
正如Sahil Mahajan Mj所说,最好的方法是重用你的对象。这不会阻止垃圾收集器运行(如上所述,它将继续运行),但它将确保GC没有很多工作要做(这节省了时间)。