Android 中的原始类型会被垃圾回收吗?

发布于 2024-08-25 07:49:00 字数 485 浏览 13 评论 0原文

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

我目前正在减少我的游戏中的每一个分配,以尝试减少垃圾收集的频率和感知的“滞后”,因此对于我创建的每个对象(例如字符串和矩形)变量,我我确保在构造函数中预先创建它,而不是在简单的 10 中创建临时变量 行函数...(我希望这是有道理的)

无论如何,我今晚又做了一些工作,我意识到我对垃圾收集的假设可能完全错误,而原始类型(int、boolean、float)是这些原始类型我在 10 行函数中创建的变量被称为 20 每秒增加我的垃圾收集问题?

所以一年前,每隔几秒我就会在 logcat 中看到一条消息,比如

GC 释放了 4010 个对象/484064 字节 101毫秒

现在我每隔 15-90 秒左右就会看到该消息...

因此,重新表述我的问题:看到此消息时是否包含原始类型(int、float、boolean 等)?

I know this may be a dumb question, but my background is more in c++ and managing my own memory.

I am currently cutting down every single allocation that I can from one of my games to try and reduce the frequency of garbage collection and perceived "lag", so for every variable that I create that is an Object (String and Rect for example) I am making sure that I create it before hand in my constructor and not create temporary variables in simple 10
line functions... (I hope that makes sense)

Anyways I was working though it some more tonight and I realized that I may be completely wrong about my assumption on garbage collection and primitive types (int, boolean, float) are these primitive type variables that I create in a 10 line function that gets called 20
times a second adding to my problem of garbage collection?

So a year ago every few seconds I would see a message in logcat like

GC freed 4010 objects / 484064 bytes in
101ms

Now I see that message every 15-90 seconds or so...

So to rephrase my question: Are primitive types (int, float, boolean, etc) included when seeing this message?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

莫言歌 2024-09-01 07:49:00

原始类型不是对象,因此它们不会导致任何垃圾收集。但是,您必须非常小心,因为由于装箱,原始类型很容易成为对象,而无需您显式这样做。

例如,如果您想要一个 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 类,这是原始整数键的容器。

Primitive types are not objects, so they do not cause any garbage collection. However, you do have to be very careful because due to boxing a primitive type can easily become an object without you explicitly doing so.

For example, if you want a HashMap<> of integer keys, you would use HashMap. Note that because "int" is not an object, it can't be used in a container. Integer is an object version of a primitive int. When you write code like this, an Integer object will automatically be created for you:

HashMap<Integer, Object> map = new HashMap<Integer, Object>();
int someNum = 12345;    // no object created.
map.put(someNum, null); // Integer object created.

Note that the exact same thing will happen if you don't use generics, but even more hidden:

HashMap map = new HashMap();
int someNum = 12345;    // no object created.
map.put(someNum, null); // Integer object created.

For this particular situation, you can use Android's SparseArray class, which is a container of primitive integer keys.

北座城市 2024-09-01 07:49:00

看来答案是否定的。在 Java 中,基元似乎被放在堆栈上,而不是放在堆中,并且只有对象被垃圾收集。我发现了很多对此的简短引用,请查看维基百科。对于一些稍微重一点的阅读,请参阅一篇关于 JVM 垃圾收集实现的论文,该论文更明确地解释了原语存储在物理上独立的内存位置中,因此它们不会被错误地包含在垃圾收集中此处。如果您想浏览一下,第 4 页是对此进行最直接解释的地方。

以下是 Android 特定线程,说明 gc 仅扫描指针以及如何它检查

It seems like the answer is no. It looks like primitives are put on the stack in Java and not in the heap and only objects are garbage collected. I found a lot of short references to this around, check Wikipedia. For some slightly heavier reading, see a paper on a JVM garbage collection implementation that explains a little more unambiguously that primitives are stored in physically separate memory locations so they are not mistakenly included in garbage collection here. If you feel like skimming, page 4 is where this is explained most directly.

here are android specific threads stating the gc only scans pointers and how it checks that

厌倦 2024-09-01 07:49:00

[注意:我还没有完整的评论权限,所以我将其添加为单独的答案。]

看起来像是添加了基元
Java中的栈而不是堆
只有对象才是垃圾
已收集。

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

Android 不运行标准
基于栈的JVM,它有自己的
基于注册的虚拟机。

这是一个真实的陈述,但它也有点误导,并且偏离了原始问题的要点。事实上,当一个方法调用另一个方法(等等)时,这些方法的激活帧在 Dalvik 实现中存储在堆栈中。不同之处在于,当单独查看激活帧时,Dalvik 激活帧内不包含可变大小的堆栈。在这方面,Dalvik 排列激活帧的方式更像是传统类 C 语言(例如 C 或 C++)的处理方式。

[Note: I don't yet have full comment privileges, so I'm adding this as a separate answer.]

It looks like primitives are put on
the stack in Java and not in the heap
and only objects are garbage
collected.

This is not quite accurate. Primitives can be held in local variables and also as the static or instance fields of classes. In the latter case, they are indeed stored on the heap, but they importantly do not have a "life" of their own and in particular aren't gc'ed separately from the object that they are contained within.

Android doesn't run a standard
stack-based JVM, it has its own
register based VM.

This is a true statement, but it's also a bit misleading and beside the point of the original question. In fact, when one method calls another (and so on), the activation frames of these methods are stored on a stack in the Dalvik implementation. The difference is that, when looking at an activation frame in isolation, Dalvik activation frames don't contain within them a variable-size stack. In this regard, the way Dalvik arranges activation frames is more like how they are handled for traditional C-like languages (such as C or C++).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文