Android开发Android技术知识Android开发经验谈

JVM内存模型和垃圾回收

2018-09-05  本文已影响12人  可乐游侠

在开发过程中,常接触到内存内存,但内存究竟长什么样呢?

JVM内存模型

运行时数据区

jvm中将内存分为程序计数器、Java虚拟机栈、本地方法栈、堆、方法区五个部分。其中Java虚拟机栈、本地方法栈和程序计数器是每个线程独有的,而堆和方法区是所有线程共享的。下面分别介绍各个内存区域。

堆内存模型

堆内存模型

堆内又分为新生代、老年代、永久代。当最大堆体积大于最小堆体积的时候,堆创建的时候不会占用全部的堆空间,因此留下一部分暂时未被使用的空间,就是Virtual。

  1. 新生代:大部分对象都在新生代中创建和销毁(小部分大对象直接在老年代创建),新生代内部分为一个Eden和两个Survivor。
  2. 老年代:放置长生命周期的对象。对象在新生代中达到一定的年龄之后会拷贝到老年代。如果对象太大,在新生代找不到连续的空间存放,会直接在老年代创建。
  3. 永久代:存放类元数据、常量池等,JDK 8移除了永久代,增加了元数据区。

堆空间中的垃圾回收

通常情况下,垃圾回收的流程如下:

  1. 大部分的Java对象都在Eden空间中创建,这时候两个survivor空间是空的。当Eden空间达到一定的阈值之后,触发Minor GC,将Eden中存活的对象复制到其中一个survivor中,并标记对应的年龄+1,这时候Eden空闲下来。
  2. 当Eden空间再次达到一定的阈值之后,将空的survivor作为to,有对象的survivor作为from,将Eden和from中存活的对象复制到to中,并标记对应的年龄+1。
  3. 第二步发生多次之后,有的对象存活的年龄会到达一定的阈值,复制到老年代。
  4. 老年代会发生的GC叫Major GC,取决于JVM的实现方法,一般采用标记整理,将老年代的对象进行标记,清除无用对象之后将其它对象整理到连续的内存区域。

常用的JVM的垃圾回收算法

如何确定对象是否需要回收

  1. 引用计数算法:给对象添加一个引用计数器,当对象被引用的时候就将引用计数器+1,当引用失效时,将计数器减1。计数器为0的对象就是可以回收的对象。Python使用的就是引用记数算法。但Java没有使用,因为存在循环引用的问题。
  2. 可达性分析算法:选定一些活动的对象作为GC Roots,根据对象的引用链向下搜索。如果某一个对象和GC Roots之间没有引用链条,即不可达,就视为可回收对象。GC Roots是Java虚拟机栈、本地方法栈中正在引用的对象、静态属性引用的对象和常量引用的对象。

常见的垃圾回收算法

PS: 文中图片引用自极客时间Java核心技术36讲。

极客时间分享
上一篇 下一篇

猜你喜欢

热点阅读