GC那些事儿--Android内存优化第一弹

引言

App优化以内存优化(序), 做为App优化系列中内存优化的一个小部分.html

因为内存相关知识比较生涩, 内存优化中使用到的相关工具, 也有不少专有名词. 对Java内存管理, GC, Android内存管理, Dalvik/ART等知识有一个理论的认识, 可让咱们更好的使用这些工具, 分析内存问题.java

据此, 咱们就先从理论入手, 聊聊GC那些事儿.程序员

1, 何为GC

GC 是 garbage collection 的缩写, 垃圾回收的意思. 也能够是 Garbage Collector, 也就是垃圾回收器.web

1.1 垃圾回收器

咱们先来解释下Garbage Collector(垃圾回收器).shell

内存管理, 一直是编程中的一个大的问题. 在较老的语言中, 例如C++语言中, 内存管理是显式的, 也就是说使用者本身申请内存使用, 本身释放内存. 这就是为何C++语言中除了构造函数, 还有析构函数. 咱们在建立对象的时候调用构造函数建立, 系统会在对象结束其做用域的时候调用析构函数, 咱们须要作的就是在析构函数中释放掉咱们申请的相关资源, 以便释放内存地址.编程

显然, 这种显式的由编程人员本身控制释放内存的方式很容易出问题, 忘了, 漏了, 均可能致使内存问题. 也不符合程序员要懒的特征. 服务器

故而, Java语言中引入了自动内存管理的机制, 也就是垃圾回收器. 大部分的现代面向对象语言, 也都是采用自动内存管理机制.并发

内存自动管理回收机制能够解决大部分, 但不是全部的内存问题, 这也是为何咱们要讨论内存泄露.oracle

垃圾回收器的职责

垃圾回收器有三大职责:jvm

  1. 分配内存;
  2. 确保任何被引用的对象保留在内存中;
  3. 回收不能经过引用关系找到的对象的内存.

垃圾回收的通常流程

Slice 1

1.2 相关概念

垃圾回收(GC)

垃圾回收器中有一个进程来作上面的这些事情, 这个进程查找咱们的对象引用的关系并释放其内存, 这个进程就是garbage collection(垃圾回收), 也就是咱们常说的GC.

Heap和Stack

简单说下:

  • Heap内存是指java运行环境用来分配给对象和JRE类的内存. 是应用的内存空间.
  • Stack内存是相对于线程Thread而言的, 它保存线程中方法中短时间存在的变量值和对Heap中对象的引用等.
  • Stack内存, 顾名思义, 是类Stack方式, 老是后进先出(LIFO)的.
  • 咱们一般说的GC的针对Heap内存的. 由于Stack内存至关因而随用随销的.

GC Root

直译GC根, 咱们姑且不译了吧.
所谓GC Root咱们能够理解为是一个Heap内存以外的对象, 一般包括但不只限于以下几种:

  • System Class 系统Class Loader加载的类. 例如java运行环境中rt.jar中类, 好比java.util.* package中的类.
  • Thread 运行中的线程
  • JNI 中的本地/全局变量, 用户自定义的JNI代码或是JVM内部的.
  • Busy Monitor 任何调用了wait()或notify()方法, 或是同步化的(synchronized)的东西. 能够理解为同步监控器.
  • Java本地实例, 还在运行的Thread的stack中的方法建立的对象.

活对象/垃圾

若是这个对象是引用可达的, 则称之为活的(live), 反之, 若是这个对象引用不可达, 则称之为死的(dead), 也能够称之为垃圾(garbage).

这个引用可达与不可达就是相对于GC Root来讲的:

2, Java的内存管理机制

2.1 关于JVM

咱们日常在查看咱们的java版本时, 你会发现:

$ java -version
java version "1.8.0_74"
Java(TM) SE Runtime Environment (build 1.8.0_74-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode)复制代码

其中有个HotSpot VM的东西, 那么这个是什么呢? 和JVM有什么关系呢?

在此简单说下, 以便行文:

  • JVM, Java虚拟机, 能够简单理解为一种技术思想, 虚拟技术理念.
  • HotSpot VM是JVM的一种实现, 包含了服务器版和桌面应用程序版, 现时由Oracle维护并发布.

咱们当前使用的sun(oracle)的java版本(应该是1.3以上)都是内置的HotSpot VM实现. 因此接下来的分析也都是基于HotSpot VM的, 可是仍是简称JVM.

2.2 JVM内存区域

JVM使用分代式的内存管理方式, 将Heap分红三代 --- 新生代, 老一代, 持久代.

  • Young Generation

    • 新生代.
    • 全部new的对象.
    • 该区域的内存管理使用minor garbage collection(小GC).
    • 更进一步分红Eden space, Survivor 0 和 Survivor 1 三个部分.
  • Old Generation

    • 老年区.
    • 新生代中执行小粒度的GC幸存下来的"老"对象.
    • 该区域的内存管理使用major garbage collection(大GC).
  • Permanent Generation

    • 持久代.
    • 包含应用的类/方法信息, 以及JRE库的类和方法信息.

小GC执行很是频繁, 并且速度特别快.
大GC通常会比小GC慢十倍以上.
大小GC都会发出"Stop the World"事件, 也就是说中断程序运行, 直至GC完成. 这也是咱们在App优化之消除卡顿中为何说频繁GC会形成用户感知卡顿.

3, GC的流程

了解了内存Heap的几个区域, 咱们再来看下垃圾收集器是怎么利用这几个区域来管理内存和回收垃圾的.

1. 建立新的对象

每当咱们使用new建立一个对象时, 这个对象会被分配到新生代Eden区域:

2. 当Eden区域满时
当Eden区域内存被分配完时, 小GC程序被触发:

引用可达的对象会移到Survivor(幸存者)区域--S0, 而后清空Eden区域, 此时引用不可达的对象会直接删除, 内存回收, 以下:

3. Eden再次满时
当Eden区域再次分配完后, 小GC执行, 引用可达的对象会移到Survivor(幸存者)区域, 而引用不可达的对象会跟随Eden的清空而删除回收.

须要注意的是, 此次引用可达的对象移动到的是S1的幸存者区.
并且, S0区域也会执行小GC, 将其中还引用可达的对象移动到S1区, 且年龄+1. 而后清空S0, 回收其中引用不可达的对象.

此时, 全部引用可达的对象都在S1区, 且S1区的对象存在不一样的年龄. 以下:

当Eden第三次满时, S0和S1的角色互换了:

依此循环.

4. 当Survivor区的对象年龄达到"老年线"时
上面1~3循环, Survivor区的对象年龄也会持续增加, 当其中某些对象年龄达到"老年线", 例如8岁时, 它们会"晋升"到老年区.

如此1~4步重复, 大致流程是这样的

参考


转载请注明出处, 欢迎你们分享到朋友圈, 微博~

相关文章
相关标签/搜索