代码之家  ›  专栏  ›  技术社区  ›  snctln

原始类型是否在Android中被垃圾收集?

  •  15
  • snctln  · 技术社区  · 16 年前

    我知道这可能是一个愚蠢的问题,但我的背景更多的是C++和管理我自己的记忆。

    我目前正在减少每一个分配,我可以从我的一个游戏,试图减少垃圾收集的频率和感知到的“滞后”,所以对于我创建的每一个变量,这是一个对象(例如字符串和rect),我要确保我创建它之前交给我的反对而不是在简单的10中创建临时变量 行函数…(我希望这是有道理的)

    不管怎么说,我今天晚上做了更多的工作,我意识到我对垃圾收集的假设可能是完全错误的,基本类型(int,boolean,float)是我在一个10行函数中创建的这些基本类型变量,这个函数被称为20 我的垃圾收集问题一秒增加几次?

    所以一年前每隔几秒钟,我就会看到一条像logcat一样的信息

    gc释放4010个对象/484064字节 101MS

    现在我每隔15-90秒左右就会看到这个信息……

    所以,要重新表述我的问题:当看到这个消息时,是否包括原始类型(int、float、boolean等)?

    3 回复  |  直到 15 年前
        1
  •  25
  •   Christopher Orr    16 年前

    基元类型不是对象,因此不会导致任何垃圾收集。但是,您必须非常小心,因为由于装箱的原因,如果不显式地执行此操作,原始类型很容易成为对象。

    例如,如果您想要一个整数键的hashmap<gt;,您将使用hashmap。注意,因为“in t”不是对象,所以不能在容器中使用。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类,它是一个包含原始整数密钥的容器。

        2
  •  6
  •   jqpubliq    16 年前

    似乎答案是否定的。它看起来像原语在Java中堆栈而不是堆中,而只有对象是垃圾收集的。我发现了很多关于这个的简短参考资料,查阅维基百科。对于一些稍微重一些的阅读,请参阅一篇关于JVM垃圾收集实现的文章,它更明确地解释了原语存储在物理上独立的内存位置,因此它们不会被错误地包含在垃圾收集中。 here . 如果你想略读,第4页是最直接的解释。

    以下是特定于Android的线程,说明了GC only scans pointers 以及如何 it checks that

        3
  •  2
  •   danfuzz    15 年前

    [注意:我还没有完全的评论权限,因此我将添加此作为单独的答案。]

    看起来像是穿上了原语 Java中的堆栈而不是堆中的堆栈 只有物体是垃圾 收集。

    这不太准确。基元可以保存在局部变量中,也可以作为类的静态或实例字段。在后一种情况下,它们确实存储在堆中,但重要的是,它们没有自己的“生命”,特别是,它们与包含在其中的对象不分开。

    Android没有运行标准 基于堆栈的JVM,它有自己的 基于寄存器的虚拟机。

    这是一个真实的陈述,但它也有点误导,与最初的问题无关。事实上,当一个方法调用另一个方法(等等)时,这些方法的激活帧存储在dalvik实现中的堆栈上。区别在于,当孤立地查看激活帧时,dalvik激活帧不包含 在内部 它们是一个可变大小的堆栈。在这点上,Dalvik安排激活框架的方式更像是如何处理传统的C类语言(如C或C++)。