我知道这可能是一个愚蠢的问题,但我的背景更多是用c ++和管理自己的记忆。
我目前正在削减我可以从我的一个游戏中尝试减少垃圾收集频率和感知“滞后”的每一个分配,因此对于我创建的每个变量都是一个Object(String和Rect for示例)我确保在构造函数中创建它之前创建它,而不是在简单的10中创建临时变量 线功能......(我希望这很有意义)
无论如何我今晚工作得更多了,我意识到我对垃圾收集的假设可能完全错了,原始类型(int,boolean,float)是我在10行函数中创建的这些原始类型变量被称为20 一秒钟加入我的垃圾收集问题?
所以一年前我每隔几秒就会在logcat中看到一条消息,如
GC释放了4010个对象/ 484064字节 101ms
现在我每隔15-90秒左右看到一条消息......
所以重新解释一下我的问题:看到这条消息时是否包含原始类型(int,float,boolean等)?
答案 0 :(得分:25)
原始类型不是对象,因此它们不会导致任何垃圾回收。但是,你必须非常小心,因为由于装箱,原始类型很容易成为一个对象而你没有明确这样做。
例如,如果你想要一个HashMap<>对于整数键,您将使用HashMap。请注意,因为“int”不是对象,所以它不能在容器中使用。 Integer是原始int的对象版本。当您编写这样的代码时,将自动为您创建一个Integer对象:
HashMap<Integer, Object> map = new HashMap<Integer, Object>();
int someNum = 12345; // no object created.
map.put(someNum, null); // Integer object created.
请注意,如果您不使用泛型,则会发生完全相同的事情,但更隐蔽:
HashMap map = new HashMap();
int someNum = 12345; // no object created.
map.put(someNum, null); // Integer object created.
对于这种特殊情况,您可以使用Android的SparseArray类,它是原始整数键的容器。
答案 1 :(得分:6)
似乎答案是否定的。它看起来像是在Java中堆栈而不是堆中的基元,只有对象被垃圾收集。我找到了很多对此的简短引用,请查看维基百科。对于稍微重读一些,请参阅有关JVM垃圾收集实现的文章,该文章更明确地解释了基元存储在物理上独立的内存位置,因此它们不会错误地包含在垃圾收集here中。如果你想略读,第4页是最直接解释的地方。
这里是特定于Android的线程,说明了gc only scans pointers以及it checks that
答案 2 :(得分:2)
[注意:我还没有完整的评论权限,所以我将其添加为单独的答案。]
看起来像原始人一样 Java中的堆栈而不是堆中的堆栈 只有对象是垃圾 收集。
这不太准确。基元可以保存在局部变量中,也可以作为类的静态或实例字段。在后一种情况下,它们确实存储在堆上,但它们重要的是没有它们自己的“生命”,特别是它们与它们所包含的对象不分开。
Android没有运行标准 基于堆栈的JVM,它有自己的 基于寄存器的VM。
这是一个真实的陈述,但它也有点误导,并且在原始问题的旁边。实际上,当一个方法调用另一个方法(依此类推)时,这些方法的激活帧存储在Dalvik实现中的堆栈上。不同之处在于,当单独查看激活帧时,Dalvik激活帧不包含 in 它们是可变大小的堆栈。在这方面,Dalvik安排激活帧的方式更像是传统C语言(如C或C ++)的处理方式。