android - 验证为什么对象只在第二次垃圾收集运行时被垃圾收集

标签 android garbage-collection

出于学习目的,我目前正在试验垃圾收集(Pixel 2,Android 10 -> ART)。我对以下实验的观察是 CountActivity在第一次显式垃圾收集运行时永远不会被删除,而只会在第二次显式垃圾收集运行时被删除。我想了解为什么它在第一次运行时没有被删除。我认为这是由于某种分代垃圾收集,但我想验证它。我如何“观察”垃圾收集的作用?例如。是否可以看到垃圾收集对堆进行分组的内部代?

我的测试示例如下:

  • MainActivity ,其中显示一个按钮“显示 CountActivity”
  • CountActivityMainActivity 中的按钮“显示 CountActivity”时显示被按下。
  • 我结束了CountActivity使用我的系统返回键

  • 在此之后,我强制运行显式垃圾收集,捕获一个堆。 CountActivity还在那里。在强制执行第二次显式垃圾收集并再次捕获堆后,CountActivity离开了。现在我仍然想了解为什么需要运行两次垃圾收集。

    主要 Activity
    class MainActivity : AppCompatActivity() {
    
      override fun onCreate(savedInstanceState: Bundle?) {
        setTheme(R.style.AppTheme)
        super.onCreate(savedInstanceState)
    
        setContentView(R.layout.activity_main)
    
        buttonStart.setOnClickListener {
          showCountActivity()
        }
    
      }
    
      private fun showCountActivity() {
        val intent = Intent(this, CountActivity::class.java)
        startActivity(intent)
      }
    
    }
    

    计数 Activity
    class CountActivity : AppCompatActivity() {
    
      override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_count)
      }
    }
    

    最佳答案

    ART(Android 运行时)使用所谓的 generational garbage collector ,它基本上根据创建这些对象的时间创建对象桶(理论上,较新的对象更有可能需要被垃圾收集,因为这是所有临时对象(构建器、其他中间对象等)将结束的地方因此,垃圾收集不一定会收集所有代的对象。

    以下是有关 Android 垃圾收集器工作原理的一些基本信息:https://developer.android.com/topic/performance/memory-overview

    您可以通过在 Android Studio 中获取和分析堆转储来验证这一点,并注意没有从相关对象到任何 GC 根的路径。

    这里有一些关于 GC 细节的非常详细的文档(更可能对从事 ART 本身的工作的人有用,但仍然提供信息 - ergonomics 部分特别讨论了世代收集):https://source.android.com/devices/tech/dalvik/gc-debug

    关于android - 验证为什么对象只在第二次垃圾收集运行时被垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60919596/

    相关文章:

    java - 想要阻止毫秒增加

    java - 局部变量的垃圾收集

    haskell - 当在 C 中管理(取消)分配时,Haskell 运行时中的垃圾收集器问题

    android - 由于 androidx.core 库不匹配,无法构建项目

    android - Android App 中的后退按钮无法退出应用程序

    关闭时的Android对话框动画

    android - 在 fragment 中使用时 ListView 与 TabLayout 和按钮重叠

    通过 gc() 静默释放内存

    mongodb - 使用 MongoDB 的 Grails 中的内存泄漏

    java - GC 如何在范围中间工作