JVM学习总结四——内存分配策略
之前几篇我们介绍了jvm的内存模型以及垃圾回收机制,而本篇我们将介绍几个JVM中对象在分配内存是应该遵循的策略。毕竟,想要去优化程序,不仅要考虑垃圾回收的过程,还要从对象内存分配的角度减少gc的代价。
一、gc日志格式
在这里先介绍一下gc日志的格式,分析gc日志是了解gc过程最直接的方式。对于大量的日志分析,直接查看日志文件当然不方便,我们一般会使用日志分析工具,后边会有介绍,但是对于简短的日志(如十几条),一般直接查看就行了。开启日志输出的JVM参数如下:
-XX:+PrintGCDetails //打印gc日志
-XX:+PrintGCDateStamps //打印时间
-Xloggc:gc.log //输出路径
对应的日志输出格式如下(采用不同参数或不同虚拟机可能不同,但大同小异):
2014-03-09T18:10:47.639+0800: 36.408: [GC 36.408: [DefNew: 35072K->4352K(39424K), 0.0108988 secs] 75088K->45293K(126848K), 0.0109419 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
2014-03-09T18:10:48.562+0800: 37.331: [Full GC 37.343: [Tenured: 40941K->42890K(87424K), 0.1340821 secs] 62210K->42890K(126848K), [Perm : 36863K->36863K(36864K)], 0.1341736 secs] [Times: user=0.13 sys=0.00, real=0.15 secs]
35072K->4352K(39424K):gc前使用内存大小->gc后使用大小(该区域总大小)
2014-03-09T18:10:47.639+0800: gc时间
36.408: gc耗时
GC 36.408: 表示停顿类型和停顿时间,如果是Full表示gc是Stop-The-World的
DefNew: Tenured: Perm : gc发生的区域,DefNew年轻代;Tenured年老代;Perm永久代
Times: user=0.13 sys=0.00, real=0.15 secs user:用户态耗时;sys:内核态耗时;real:gc从开始到结束消耗的Wall Clock Time耗时(墙钟时间,名字好怪,包括各种非运算的等待耗时和cpu耗时)
二、内存分配策略
1、对象优先在Eden分配
新的对象大多数情况下在Eden去分配,这样在Eden区域没有足够空间时,JVM会首先进行Minor Gc,仅对Eden进行gc,并将符合条件的对象移至年老代。这样如果Eden在gc后满足新对象的空间需求,则能避免进行Full GC。
2、大对象直接进入年老代
这一点十分好理解,多数情况下大对象的生命周期是相对较长的,而大对象如果分配在Eden,不仅占用大量空间,触发gc,还可能会在Eden区/两个Survivor区之间来回复制,十分耗费资源。因此,多数时候对于大对象,应该直接分配至年老代,开始用-XX:PertenureSizeThreshold参数指定直接分配年老代的大小。
3、长期存活的对象进入年老代
一般经过多次Minor GC而不死的对象,继续活下去的可能新更大,因此应该进入年老代。为了判断哪些对象长期存活,虚拟机给每个对象都定义了一个Age计数器,没经历一次Minor GC就+1,可以通过-XX:MaxTenuringThreshold的值来决定age达到多少时进入年老代。
4、动态对象年龄判断
为了能更好地适应不同程序的内存状况,虚拟机并不总是要求对象的年龄必须达到MaxTenuringThreshold 才能晋升老年代,如果在 Survivor 空间中相同年龄所有对象大小的总和大于Survivor 空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold 中要求的年龄。
5、空间分配担保
在发生 Minor GC 时,虚拟机会检测之前每次晋升到老年代的平均大小是否大于老年代的剩余空间大小,如果大于,则改为直接进行一次 Full GC。如果小于,则查看 HandlePromotionFailure 设置是否允许担保失败;如果允许,那只会进行 Minor GC;如果不允许,则也要改为进行一次 Full GC。 前面提到过,新生代使用复制收集算法,但为了内存利用率,只使用其中一个 Survivor 空间来作为轮换备份,因此当出现大量对象在 Minor GC 后仍然存活的情况时(最极端就是内存回收后新生代中所有对象都存活),就需要老年代进行分配担保,让 Survivor 无法容纳的对象直接进入老年代。与生活中的贷款担保类似,老年代要进行这样的担保,前提是老年代本身还有容纳这些对象的剩余空间,一共有多少对象会活下来,在实际完成内存回收之前是无法明确知道的,所以只好取之前每一次回收晋升到老年代对象容量的平均大小值作为经验值,与老年代的剩余空间进行比较,决定是否进行 Full GC来让老年代腾出更多空间。
本篇介绍完毕,下一篇将介绍JVM监控相关的一些工具。
JVM学习总结四——内存分配策略的更多相关文章
- 深入理解JVM(5)——垃圾收集和内存分配策略
1.垃圾收集对象 垃圾收集主要是针对堆和方法区进行. 程序计数器.虚拟机栈和本地方法栈这三个区域属于线程私有的,只存在于线程的生命周期内,线程结束之后也会消失,因此不需要对这三个区域进行垃圾回收. 哪 ...
- jvm垃圾收集器与内存分配策略
一.垃圾回收 1.对象是否已经变为垃圾 1.1.引用计数法:给对象添加一个引用计数器,每当有地方引用它时,计数器就加1:当引用失效时,计数器值就减1:任何时刻计数器为0的对象就是不可能再被使用的. 这 ...
- [jvm]垃圾回收与内存分配策略
一.垃圾回收算法 概述 JVM中,当创建的对象不再被使用的时候,此时我们认为他是无用的“垃圾”:在现代主流的商用jvm中,都是通过可达性分析来判断对象是否存活的.这个算法的基本思想是通过一系列“GCR ...
- JVM垃圾收集器与内存分配策略(一)
在前面的Java自动内存管理机制(上)和Java自动内存管理机制(下)中介绍了关于JVM的一些基础知识,包括运行时数据区域划分和一些简单的参数配置,而其中也谈到了GC,但是没有深入了解,所以这里开始简 ...
- 深入理解JVM - 垃圾收集器与内存分配策略 - 第三章
引用计数算法——判断对象是否存活的算法 很多教科书判断对象是否存活的算法是这样的:给对象添加一个引用计数器,每当一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器为0的对象 ...
- jvm垃圾回收器与内存分配策略
一.判断对象存活的算法 1.引用计数算法 (1)概念:给对象中添加一个引用计数器每当有一个地方引用它时,计数器值加1:当引用失效时,计数器就减1:任何时刻计数器为0的对象就是不可能再被使用的. (2) ...
- jvm系列(二)jvm垃圾收集器与内存分配策略
众所周知,在java语言中,内存分配和回收是由jvm自动管理的.因此内存的分配和回收也是jvm三大功能之一.垃圾收集器(GC)需要完成三件事情: 哪些内存需要回收? 什么时候进行回收? 如何回收? 本 ...
- JVM·垃圾收集器与内存分配策略之垃圾回收算法!
1.垃圾回收算法 1.1.标记-清除算法(Mark-Sweep): 过程分为“标记”和“清除”两个过程.先将所有需要回收的目标统一标记,然后再统一清除. ...
- JVM·垃圾收集器与内存分配策略之对象是否可被回收!
1.判断对象已经死去/不再被引用. 1.1.引用计数算法:给对象添加引用计数器,有个地方引用就+1,引用失效就-1.任何时刻,引用为0,即判断对象死亡. 1.1.1.优点:实现 ...
随机推荐
- phpinfo中查不到memcache信息问题
已经安装了php的memcache扩展,可是怎么都不能通过phpinfo查询到,实际使用时提示扩展未安装.为什么呢?百般寻求解决方法,才发现主要有以下两点原因: 1.使用的php和安装扩展的php不是 ...
- ant风格是什么?
我们在看java技术书籍的过程中,当加载文件时总会遇到是否支持ant风格路径加载,这里说的ant风格是什么意思呢,今天我查了一下,明白了什么意思,现在总结一下 ANT通配符有三种: 通配符 说明 ? ...
- [drp 2]String、StringBuffer和StringBuilder的区别
导读:在实际运用了,我们会频繁的用到string.stringBuffer和stringBuilder这三个东西,那么,他们之间的区别是什么呢.本文主要是从拼写SQL语句的角度,来阐释他们之间的区别! ...
- sql语句小练习一
create database aaa go use aaa go create table student( sno varchar(3), sname varchar(4) not null ...
- 10 Code Coverage Tools for C & C++
Code coverage is a measure used in software testing that describes the degree to which the source co ...
- C# Java 3DES加密解密 扩展及修正\0 问题
注: C#已亲测及做扩展, Java 部分未做验证 /// <summary> /// 3DES加密解密 /// ------------------------------------- ...
- leetcode 104
104. Maximum Depth of Binary Tree Given a binary tree, find its maximum depth. The maximum depth is ...
- 通过string型类名实例化一个类
DataTable dt = new DBHelper().getIndexInfo(code_id); DataRow row = dt.Rows[0]; string dllName = row[ ...
- .NET中使用log4net
一,加载log4net引用 下载log4net.dll,我们这里使用的是.NET2.0 下载地址:http://files.cnblogs.com/gosky/log4net-1.2.13-bin-n ...
- 说一个Sublime Text 2插件、emmet(原名:zen Coding)
工具/原料 sublime Text 2 安装emmet插件 方法/步骤 生成html文档初始结构: !<tab> <!doctype html> <html lang= ...