简体   繁体   English

Java垃圾回收行为

[英]Java Garbage Collection Behavior

Does the Garbage Collector on Android devices only collect objects that are orphaned AND it considers too large, or does it collect all orphaned objects regardless of size? Android设备上的垃圾收集器是否仅收集孤立的对象并且认为它太大,还是收集所有孤立的对象而与大小无关?

I am doing a test where I rapidly push and pop an Activity on and off the stack several times and then take a look at the heap. 我正在做一个测试,在其中我快速将Activity推入并弹出堆栈几次,然后查看堆。

If the Activity in question contains no code, then I end up with several instances of it showing up in a heap dump, even after forcing a GC. 如果有问题的活动不包含任何代码,那么即使强制执行GC,我也会在堆转储中显示该活动的多个实例。

However, if I add a large variable to this activity like a large byte array, then the GC seems to behave as desired/expected. 但是,如果我向此活动添加大变量(如大字节数组),则GC似乎表现出预期/预期的行为。

Garbage collectors pay no attention to the size of the objects that they are collecting. 垃圾收集器不会注意收集的对象的大小。 They are indiscriminate. 他们是不分青红皂白的。 If the GC detects that an object is unreachable, it collects it. 如果GC检测到对象不可访问,它将收集该对象。

What you are probably observing is a different effect. 您可能观察到的是不同的效果。 A typical garbage collector only runs when the JVM determines that there is enough garbage to be worth collecting. 典型的垃圾收集器仅在JVM确定有足够的垃圾值得收集时才运行。 The problem is that the workload of a collection has two parts: 问题在于集合的工作量包含两个部分:

  1. finding unreachable objects 寻找无法到达的物体
  2. collecting the unreachable objects 收集无法到达的物体

In a typical modern collector, finding the unreachable objects involves traversing and marking all reachable objects: the unreachable objects are the ones that were not marked. 在一个典型的现代收藏家中,查找不可访问的对象涉及遍历和标记所有可访问的对象:不可访问的对象是未标记的对象。 Then collecting the unreachable objects is typically done by moving all of the reachable objects. 然后,通常通过移动所有可到达的对象来完成收集不可到达的对象的操作。

This means that the work done by the GC is proportional to the amount of non-garbage. 这意味着GC所做的工作与非垃圾的数量成正比。 Therefore, a GC will work most efficiently if the ratio of garbage to non-garbage is high. 因此,如果垃圾与非垃圾的比率很高,则GC将最有效地工作。 The simplest measure of that is when the heap is full or close to full. 最简单的方法是当堆已满或接近满时。

So what you are probably seeing is that allocation of larger objects is causing the heap to fill sooner, and triggering the GC to run. 因此,您可能会看到的是,分配较大的对象会导致堆更早填充,并触发GC运行。 When the objects are small, the heap doesn't fill, and the GC doesn't run (yet). 当对象较小时,堆不会填满,GC也不会运行(尚未)。

As for "forcing" the GC, the behavior of a System.gc() call is highly platform specific. 至于“强制” GC, System.gc()调用的行为是高度特定于平台的。 On some platforms it will trigger a full GC, on others it will do absolutely nothing ... and various points in between. 在某些平台上,它将触发完整的GC,在另一些平台上,它将完全不起作用...介于两者之间。

Eventually it collects everything regardless of size. 最终,无论大小如何,它都会收集所有东西。 What it collects when after it becomes elligible for collection is implementation specific and should not be relied upon. 在变得可收集之后,它所收集的内容是特定于实现的,因此不应依赖。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM