引言

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

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

据此, 我们就先从理论入手, 聊聊GC那些事儿.

1, 何为GC

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

1.1 垃圾回收器

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

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

显然, 这种显式的由编程人员自己控制释放内存的方式很容易出问题, 忘了, 漏了, 都可能导致内存问题. 也不符合程序员要懒的特征.

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

内存自动管理回收机制可以解决大部分, 但不是所有的内存问题, 这也是为什么我们要讨论内存泄露.

垃圾回收器的职责

垃圾回收器有三大职责:

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

垃圾回收的一般流程

gc process

1.2 相关概念

垃圾回收(GC)

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

Heap和Stack

简单说下:

  • Heap内存是指java运行环境用来分配给对象和JRE类的内存. 是应用的内存空间.
  • Stack内存是相对于线程Thread而言的, 它保存线程中方法中短期存在的变量值和对Heap中对象的引用等.
  • Stack内存, 顾名思义, 是类Stack方式, 总是后进先出(LIFO)的.
  • 我们通常说的GC的针对Heap内存的. 因为Stack内存相当于是随用随销的.
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来说的:

gc-roots

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分成三代 --- 新生代, 老一代, 持久代.

Hotspot heap structure
  • 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区域:

object allocation

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

Eden filling

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

aged

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

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

此时, 所有引用可达的对象都在S1区, 且S1区的对象存在不同的年龄. 如下:

next filling

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

s0s1

依此循环.

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

old aged

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

gc flow

作者:anly_jun
链接:https://www.jianshu.com/p/5db05db4f5ab
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Android内存优化5 了解java GC 垃圾回收机制3的更多相关文章

  1. Android内存优化3 了解java GC 垃圾回收机制1

    开篇废话 如果我们想要进行内存优化的工作,还是需要了解一下,但这一块的知识属于纯理论的,有可能看起来会有点枯燥,我尽量把这一篇的内容按照一定的逻辑来走一遍.首先,我们为什么要学习垃圾回收的机制,我大概 ...

  2. Android内存优化4 了解java GC 垃圾回收机制2 GC执行finalize的过程

    1. finalize的作用 finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法. finalize()与C++中的析构函数 ...

  3. 面试官,不要再问我“Java GC垃圾回收机制”了

    Java GC垃圾回收几乎是面试必问的JVM问题之一,本篇文章带领大家了解Java GC的底层原理,图文并茂,突破学习及面试瓶颈. 楔子-JVM内存结构补充 在上篇<JVM之内存结构详解> ...

  4. 乐字节Java|GC垃圾回收机制、package和import

    本文接上一篇:乐字节Java|this关键字.static关键字.block块.本文是接着讲述JavaGC垃圾回收机制.package 和 import语句. 一.GC垃圾回收机制 GC全名:Garb ...

  5. Java GC - 垃圾回收机制

    1.简介 对于Java developer来说,了解JVM GC工作原理能够帮助我们开发出更优秀的应用,同时在处理JVM瓶颈时能够更加自由.在最近一年的应用开发中能体会到这些知识带来的好处,并且让我们 ...

  6. JAVA gc垃圾回收机制

    一.GC概要   JVM堆相关知识     为什么先说JVM堆?     JVM的堆是Java对象的活动空间,程序中的类的对象从中分配空间,其存储着正在运行着的应用程序用到的所有对象.这些对象的建立方 ...

  7. 转载 JAVA gc垃圾回收机制

    thanks:https://m.oschina.net/u/123553 一.GC概要 JVM堆相关知识    为什么先说JVM堆?    JVM的堆是Java对象的活动空间,程序中的类的对象从中分 ...

  8. java GC垃圾回收机制G1、CMS

    CMS(Concurrent Mark-Sweep)是以牺牲吞吐量为代价来获得最短回收停顿时间.对于要求服务器响应速度的应用上,这种垃圾回收器非常适合.在启动JVM参数加上-XX:+UseConcMa ...

  9. java面试题之----JVM架构和GC垃圾回收机制详解

    JVM架构和GC垃圾回收机制详解 jvm,jre,jdk三者之间的关系 JRE (Java Run Environment):JRE包含了java底层的类库,该类库是由c/c++编写实现的 JDK ( ...

随机推荐

  1. Android各层推荐开发书籍及参考资料!!!

    Android各层推荐开发书籍及参考资料 转自:http://blog.csdn.net/fancylovejava/article/details/8657058 Android系统按照架构来说一共 ...

  2. linux命令(16):mv命令

    移动文件:mv /mnt/test.log /home 移动目录:mv -f /mnt/test /home [带-f参数如目的已存在同名文件,则直接覆盖掉] 文件改名:mv /mnt/test /m ...

  3. 《java并发编程实战》读书笔记12--原子变量,非阻塞算法,CAS

    第15章 原子变量与非阻塞同步机制 近年来,在并发算法领域的大多数研究都侧重于非阻塞算法,这种算法用底层的原子机器指令(例如比较并交换指令)代替锁老确保数据在并发访问中的一致性. 15.1 锁的劣势 ...

  4. 《java并发编程实战》读书笔记8--死锁,性能与可伸缩性,锁粒度锁分解锁分段

    第10章 避免活跃性危险 10.1 死锁 -10.1.1 锁顺序死锁 最简单的一种死锁形式: -10.1.2 动态的锁顺序死锁 可以通过下面的方法来解决: -10.1.3 在协作对象之间发生死锁 -1 ...

  5. LCA离线算法Tarjan的模板

    hdu 2586:题意:输入n个点的n-1条边的树,m组询问任意点 a b之间的最短距离 思路:LCA中的Tarjan算法,RMQ还不会.. #include <stdio.h> #inc ...

  6. .NET对IO的基本操作集合

    分享一下对IO的基本使用,很简单的东西,不需要记住,用的时候看一下就可以了. 个人对IO的使用很少,记录日志,保存一些数据,保存文件,其他的基本上很少用到,做商城类的项目应该会用到很多 1.先配置一下 ...

  7. 前端读者 | 百度前端编码规范(CSS)

    本文来自:百度FEX 1 前言 CSS作为网页样式的描述语言,在百度一直有着广泛的应用.本文档的目标是使CSS代码风格保持一致,容易被理解和被维护. 虽然本文档是针对CSS设计的,但是在使用各种CSS ...

  8. #1054 - Unknown column 'category' in 'field list'

    导致这个问题的原因有: 1.确实没有这个字段 2.写错表了,你以为写到想要的表,没想到写到别处去了,当然没有这个字段了,这时候检查一下sql语句是不是选错了表,或者选错了数据库

  9. centos python 安装 readability

    yum install libxslt-devel pip install readability-lxml

  10. python之面向对象编程二

    类的成员 类的成员可以分为三大类:字段.方法.属性. 字段:普通字段.静态字段. 方法:普通方法.类方法.静态方法 属性:普通属性. 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多 ...