应用JConsole学习Java GC
应用JConsole学习Java GC
关于Java GC的知识,好多地方都讲了很多,今天我用JConsole来学习一下Java GC的原理。
GC原理
在我的上一篇中介绍了Java运行时数据区,在了解这些的基础上,对Java GC的理解能更清晰一些。
简单来讲,Java的内存分为堆和栈,其中堆是程序员用的内存,栈是系统用的内存。(这句话不一定正确,但可以这么理解)Java的内存管理主要是管理对象的分配和释放,或者说内存的分配和回收。在C或C++语言里面,内存是要自己控制的,new之后要delete掉,否则很容易出现内存泄漏。(还记得当时写C的痛苦,不过通过写C代码,很好的了解了内存的分配机制)在Java里面,分配内存和回收内存的事情是Jvm来管的。
Jvm有自己的机制来管理内存,具体的细节算法这里不讲,主要讲大概的处理方式。Jvm的GC主要处理堆内存,JVM内存模型中的堆可以细分为Young Generation和Old Generation(又称为Tenure Space),其中Young Generation又分为Eden Space(Eden是伊甸园的意思,老鹰乐队有首歌叫Long Road out of Eden)和Survivor spaces。如下图所示:
具体GC的过程如下:
- 在Young Generation中,有一个叫Eden Space的空间,主要是用来存放新生的对象,还有两个Survivor Spaces(from、to),它们的大小总是一样,它们用来存放每次垃圾回收后存活下来的对象。
- 在Old Generation中,主要存放应用程序中生命周期长的内存对象。
- 在Young Generation块中,垃圾回收一般用Copying的算法,速度快。每次GC的时候,存活下来的对象首先由Eden拷贝到某个SurvivorSpace,当Survivor Space空间满了后,剩下的live对象就被直接拷贝到OldGeneration中去。因此,每次GC后,Eden内存块会被清空。
- 在Old Generation块中,垃圾回收一般用mark-compact的算法,速度慢些,但减少内存要求。
- 垃圾回收分多级,0级为全部(Full)的垃圾回收,会回收OLD段中的垃圾;1级或以上为部分垃圾回收,只会回收Young中的垃圾,内存溢出通常发生于OLD段或Perm段垃圾回收后,仍然无内存空间容纳新的Java对象的情况。
翻译成为更简单的语言:
- 内存首先在Eden中分配;
- Eden中满了之后,挪到Survivor Space,清空Eden;
- Survivor Space满了之后,挪到Old Generation;
- 如果这三个区域都满了,内存溢出OutOfMemory。
那上面这个过程如何得知呢?今天我就用JConsole给大家演示一下如何看GC的过程。
JConsole介绍
先介绍一下JConsole。
JConsole是什么
JConsole 是一个内置 Java 性能分析器,可以从命令行或在 GUI shell 中运行。您可以轻松地使用 JConsole(或者,它更高端的 “近亲” VisualVM )来监控 Java 应用程序性能和跟踪 Java 中的代码。
如何启动JConsole
JConsole是一个程序,在windows里面找到JConsole.exe,双击启动即可。启动之后的界面如下图所示:
可以看到,JConsole即可以连接本地进程,也可以连接远程进程。
应用JConsole学习GC
那么,如何用JConsole学习GC的过程呢?我们首先要设计一个程序,这个程序一直保持内存增长,直到发生内存泄漏。在这个过程中,我们应该JConsole观察GC的过程。
写一个内存泄漏的程序
写一个内存泄漏的程序比较简单,读一个很大的文件到内存中,直至内存溢出,代码如下:
package com.chzhao.test;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class StringTest {
public static void main(String[] args) throws InterruptedException,
IOException {
List<String> list = new ArrayList<String>();
String file = "d:/wisdombud-unicom.log.2014-12-05";
BufferedReader in = null;
in = new BufferedReader(new FileReader(file));
while (true) {
String lineMsg = in.readLine();
if (lineMsg == null || lineMsg.equals("")) {
break;
}
list.add(lineMsg);
Thread.sleep(10);
System.out.println(list.size());
}
in.close();
}
}
这个文件是我程序的一个日志文件,足够大,300M+
设置启动参数
除了写程序之外,为了快点出现内存泄漏,我们把启动内存调小。在Eclispse里面调VM arguments就可以,内容为:
-Xms4M -Xmx4M
我设置了4M。
通过JConsole观察
首先把程序运行起来,在通过JConsole连接到程序上。
因为我们只关心内存,切换到内存标签页。有一个下拉图表,可以观察不同的内存情况。右下角有个柱状图,显示的是堆内存和栈内存的占用情况。其中堆内存包括Eden Space、Survivor Space和Tenured Gen。如下图所示:
可以看到,随着程序的运行,Eden Space会逐渐变满,到100%之后,Eden Space会变成0%,Survivor Space会变大;Survivor Space变100%之后,会挪到Tenured Gen中,Survivor Space变0%。这个过程和上面讲到的GC过程是一样的,很直观。
也可以观察上面的曲线图,Eden Space的图是类似波形图,每次到波谷都是进行了一次GC。Tenured Gen则是类似梯田,一直向上涨,直到内存溢出。如下两张图所示。
Eden Space的波形图
Tenured Gen的波形图
在VM摘要标签页,能看到更多JVM的信息,可以看到分配的内存已经等于堆的最大值了,所以内存溢出。(为什么堆的最大值是5942Kb我没搞明白,不应该小于4M吗?如果哪位懂请指点一下。)
结论
通过JConsole工具学习GC的过程,生动形象,很容易明白GC是如何进行的。然而这些知识都属于GC的基础知识,如果要了解更多GC的知识,还要多学习。
参考:
应用JConsole学习Java GC的更多相关文章
- Java GC回收机制
优秀Java程序员必须了解的GC工作原理 一个优秀的Java程序员必须了解GC的工作原理.如何优化GC的性能.如何与GC进行有限的交互,因为有一些应用程序对性能要求较高,例如嵌入式系统.实时系统等,只 ...
- Java GC(垃圾回收)机制知识总结
目录 Java GC系列 Java关键术语 Java HotSpot 虚拟机 JVM体系结构 Java堆内存 启动Java垃圾回收 Java垃圾回收过程 垃圾回收中实例的终结 对象什么时候符合垃圾回收 ...
- java gc的工作原理、如何优化GC的性能、如何和GC进行有效的交互
java gc的工作原理.如何优化GC的性能.如何和GC进行有效的交互 一个优秀的Java 程序员必须了解GC 的工作原理.如何优化GC的性能.如何和GC进行有效的交互,因为有一些应用程序对性能要求较 ...
- Java GC系列(4):垃圾回收监视和分析
本文由 ImportNew - lomoxy 翻译自 javapapers. 目录 垃圾回收介绍 垃圾回收是如何工作的? 垃圾回收的类别 垃圾回收监视和分析 在这个Java GC系列教程中,让我们学习 ...
- Java GC 概念摘要
很长时间,我想Java的GC做一个小小的总结,他有没有时间.根据最近看了java paper向上java gc文章,我觉得好,读读.顺便说一下,总结下. java paper的GC文章地址,里面有非常 ...
- Java GC 专家系列3:GC调优实践
本篇是”GC专家系列“的第三篇.在第一篇理解Java垃圾回收中我们学习了几种不同的GC算法的处理过程,GC的工作方式,新生代与老年代的区别.所以,你应该已经了解了JDK 7中的5种GC类型,以及每种G ...
- Java GC专家系列1:理解Java垃圾回收
了解Java的垃圾回收(GC)原理能给我们带来什么好处?对于软件工程师来说,满足技术好奇心可算是一个,但重要的是理解GC能帮忙我们更好的编写Java应用程序. 上面是我个人的主观的看法,但我相信熟练掌 ...
- JAVA GC之标记 第五节
JAVA GC之标记 第五节 OK,我们继续昨天最后留下的问题,什么是标记?怎么标记? 第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的清理. 至于怎么标记,一般有两种方 ...
- Java GC - 监控回收行为与日志分析
1. 简介 在上一篇介绍<Java GC - 垃圾回收机制>, 本文将介绍如何监控 Javc GC 行为,同时涉及一些GUI工具的使用(虽然有些已经很老并不再更新),监控GC在于判断JVM ...
随机推荐
- 字符串模式匹配sunday算法
文字部分转自:http://www.cnblogs.com/mr-ghostaqi/p/4285868.html 代码是我自己写的 今天在做LeetCode的时候,碰到一个写字符串匹配的题目: htt ...
- 一位ACM过来人的心得(转)
励志下! 刻苦的训练我打算最后稍微提一下.主要说后者:什么是有效地训练? 我想说下我的理解.很多ACMer入门的时候,都被告知:要多做题,做个500多道就变牛了.其实,这既不是充分条件.也不会是必要条 ...
- UVa 11889 (GCD) Benefit
好吧,被大白书上的入门题给卡了.=_=|| 已知LCM(A, B) = C,已知A和C,求最小的B 一开始我想当然地以为B = C / A,后来发现这时候的B不一定满足gcd(A, B) = 1 A要 ...
- Tomcat 映射虚拟目录
设置虚拟目录映射一般有两种用途: (1)把整个web应用映射到tomcat中: 如一个testapp的web应用的路径是/opt/testapp,则通过虚拟目录映射可以将其映射到tomcat(weba ...
- linux kernel 模块多文件编译
/*************************************************************************** * linux kernel 模块多文件编译 ...
- UVA 821 Page Hopping 网页跳跃(BFS,简单)
题意: 给一个无权有向图,可认为边的长度为1,求两点间的平均长度(即所有点对的长度取平均),保留3位小数.保证任意点对都可达. 思路: 简单题.直接穷举每个点,进行BFS求该点到其他点的距离.累加后除 ...
- Windows Azure® 由世纪互联运营发布MySQL Database on Azure正式商用版
我们很高兴宣布MySQL Database on Azure于2015年9月1日在中国地区正式商用.回望过去,从2014年12月对少量用户开放的预览试用,到2015年4月30日对中国用户全面开放的公共 ...
- vc2005编译ffmpeg以及ffplay
ffmpeg编译过程:1 http://ffmpeg.zeranoe.com/builds/下载官方提供的源码,win32库和dll.2 新建vc2005 console空工程,把ffmpeg.h,f ...
- Linux网络相关查询脚本
1. 查看TCP连接状态 netstat -nat |awk '{print $6}'|sort|uniq -c|sort -rnnetstat -n | awk '/^tcp/ {++S[$NF]} ...
- ios 照片编辑的view封装
转:http://www.cnblogs.com/xiaobaizhu/archive/2013/07/03/3170101.html 该控件有旋转,缩放,拖动,剪裁的功能,封装成了一个ImageCr ...