JVM 内存管理

概述

这篇文章是我学习周志明大大《深入理解Java虚拟机》内存管理章节的学习笔记.

运行时内存模型

  • 程序计数器
  • 虚拟机栈
  • 本地方法栈
  • 方法区(永久代)
  • 堆(年轻代和老年代)
  • 直接内存(NIO堆外内存)
内存分配比例
  • 年轻代一般占三到五分之一;
  • 永久代在32位JDK默认64M, 在64位JDK默认85M, 我们可以设置大一点,128M,256M
  • JDK8 没有永久代, 替换为MetaSpace, MetaSpace是Native Memory, 大小限制取决于系统内存大小
程序计数器
  1. 程序计数器记录下一条需要执行的指令,分支, 循环, 跳转, 异常处理, 线程回复依赖此计数器
  2. 程序计数器是线程私有的空间
  3. 虚拟机执行Native方法时,计数器为空
  4. 此区域没有规定任何OutOfMemoryError异常
虚拟机栈
  1. 虚拟机栈是Java方法执行的内存模型, 每个方法调用同时创建一个栈帧. 栈帧保存了局部变量表, 操作数栈, 动态链接, 方法出口等信息.

  2. 局部变量表所需的空间在编译时确定. 64位的long和double占用2个局部变量空间(slot), 其他数据类型占用1个(包含reference类型).

  3. 虚拟机栈是线程私有的空间
  4. 此区域规定了OutOfMemoryError和StackOverFlowError
本地方法栈
  1. 此内存区域和虚拟机栈功能相似, 只是虚拟机栈用来执行Java code, 本地方法栈是为虚拟机使用的Native方法服务.

  2. 虚拟机栈可能和本地方法栈合二为一(如: Oracle Hotspot虚拟机).

方法区
  1. 用于存储加载的类信息, 常量, 静态变量, JIT编译后的代码数据.
  2. JVM描述此区域为堆的一部分.
  3. JVM规范对方法区限制宽松, 可以选择不实现垃圾回收(所以叫永久代).
  4. 此区域的回收目标是对常量池的回收和类型的卸载.
常量池
  1. 用于存放编译期生成的字面量和符号引用(直接引用也会放到常量池).这部分内容在类加载后存放到常量池.
  2. 常量池具备动态性.常量不一定在编译器产生, 运行时也可以将常量放入常量池(如: String的intern() 方法).
  3. 并不是声明了为final的变量都会进入常量池
  1. 此区域的唯一目的是存放对象实例. 但并不是所有对象实例都在堆上分配.有栈上分配,标量替换等优化技术.

  2. 堆可以划分为 新生代和老年代. 新生代可分为Eden , Survivor , to区(一般比例为8:1:1).

  3. 堆内存可以不连续, 逻辑上连续即可.

直接内存
  1. NIO库中可以使用.
  2. 直接内存并不是JVM运行时数据区的一部分.
  3. 此区域规定了OutOfMemoryError异常.

内存回收

对象死亡判定
  1. 引用计数器
  2. GC ROOT算法
垃圾回收算法
  1. 标记-清除法(最基本的)
  2. 标记-复制法
  3. 标记-整理

一般来说, 年轻代使用标记-复制法, 老年代使用标记整理法

垃圾收集器
收集器说明
Serial 使用单线程进行垃圾收集 2. 垃圾收集工作时, 暂停所有工作线程 3.暂停时间不可控制
Serial OldSerial收集器的老年代版本
ParNewSerial收集器的多线程版本, 在多CPU下,效率更高, 单CPU就不如Serial, 毕竟会增加线程切换开销.
Parallel Scavenge 新生代收集器 2. 关注吞吐量. 吞吐量 = 用户代码运行时间/(用户代码运行时间 + 垃圾收集时间). 吞吐量的值通过-XX:MaxGCPausemills和-XX:GCTimeRatio参数控制.
Parallel OldParallel Scavenge老年代版本.
CMS (Concurrent Marked Sweep) 基于标记-清除算法 2. 过程是-初始标记-并发标记-重新标记-并发清除 3. 缺点是对CPU资源敏感, 无法处理浮动垃圾, 基于标记清除算法, 容易产生内存碎片
G1 基于标记-整理算法 2. 可以精确控制停顿时间 3. 原理是将堆分为多个Region,维护一个列表记录垃圾堆积程度, 根据设定的停顿时间,优先回收垃圾最多的区域(Garbage First).

内存分配策略

  1. 对象优先在Eden分配
  2. 大对象(长字符串和大数组)直接进入老年代(所以程序中出现大量朝生夕死的大对象非常可怕).
  3. 长期存活的对象直接进入老年代, 通过-XX: MaxTenuringThreshold参数控制, 默认值为15.
  4. 动态年龄判定(并不是一定要达到某个年龄才可以进入老年代,如果Suvivor空间中相同年龄所有对象的大小总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代.)
  5. 空间分配担保

参考资料

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值