应用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的过程如下:

  1. 在Young Generation中,有一个叫Eden Space的空间,主要是用来存放新生的对象,还有两个Survivor Spaces(from、to),它们的大小总是一样,它们用来存放每次垃圾回收后存活下来的对象。
  2. 在Old Generation中,主要存放应用程序中生命周期长的内存对象。
  3. 在Young Generation块中,垃圾回收一般用Copying的算法,速度快。每次GC的时候,存活下来的对象首先由Eden拷贝到某个SurvivorSpace,当Survivor Space空间满了后,剩下的live对象就被直接拷贝到OldGeneration中去。因此,每次GC后,Eden内存块会被清空。
  4. 在Old Generation块中,垃圾回收一般用mark-compact的算法,速度慢些,但减少内存要求。
  5. 垃圾回收分多级,0级为全部(Full)的垃圾回收,会回收OLD段中的垃圾;1级或以上为部分垃圾回收,只会回收Young中的垃圾,内存溢出通常发生于OLD段或Perm段垃圾回收后,仍然无内存空间容纳新的Java对象的情况。

翻译成为更简单的语言:

  1. 内存首先在Eden中分配;
  2. Eden中满了之后,挪到Survivor Space,清空Eden;
  3. Survivor Space满了之后,挪到Old Generation;
  1. 如果这三个区域都满了,内存溢出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的更多相关文章

  1. Java GC回收机制

    优秀Java程序员必须了解的GC工作原理 一个优秀的Java程序员必须了解GC的工作原理.如何优化GC的性能.如何与GC进行有限的交互,因为有一些应用程序对性能要求较高,例如嵌入式系统.实时系统等,只 ...

  2. Java GC(垃圾回收)机制知识总结

    目录 Java GC系列 Java关键术语 Java HotSpot 虚拟机 JVM体系结构 Java堆内存 启动Java垃圾回收 Java垃圾回收过程 垃圾回收中实例的终结 对象什么时候符合垃圾回收 ...

  3. java gc的工作原理、如何优化GC的性能、如何和GC进行有效的交互

    java gc的工作原理.如何优化GC的性能.如何和GC进行有效的交互 一个优秀的Java 程序员必须了解GC 的工作原理.如何优化GC的性能.如何和GC进行有效的交互,因为有一些应用程序对性能要求较 ...

  4. Java GC系列(4):垃圾回收监视和分析

    本文由 ImportNew - lomoxy 翻译自 javapapers. 目录 垃圾回收介绍 垃圾回收是如何工作的? 垃圾回收的类别 垃圾回收监视和分析 在这个Java GC系列教程中,让我们学习 ...

  5. Java GC 概念摘要

    很长时间,我想Java的GC做一个小小的总结,他有没有时间.根据最近看了java paper向上java gc文章,我觉得好,读读.顺便说一下,总结下. java paper的GC文章地址,里面有非常 ...

  6. Java GC 专家系列3:GC调优实践

    本篇是”GC专家系列“的第三篇.在第一篇理解Java垃圾回收中我们学习了几种不同的GC算法的处理过程,GC的工作方式,新生代与老年代的区别.所以,你应该已经了解了JDK 7中的5种GC类型,以及每种G ...

  7. Java GC专家系列1:理解Java垃圾回收

    了解Java的垃圾回收(GC)原理能给我们带来什么好处?对于软件工程师来说,满足技术好奇心可算是一个,但重要的是理解GC能帮忙我们更好的编写Java应用程序. 上面是我个人的主观的看法,但我相信熟练掌 ...

  8. JAVA GC之标记 第五节

    JAVA GC之标记  第五节 OK,我们继续昨天最后留下的问题,什么是标记?怎么标记? 第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的清理. 至于怎么标记,一般有两种方 ...

  9. Java GC - 监控回收行为与日志分析

    1. 简介 在上一篇介绍<Java GC - 垃圾回收机制>, 本文将介绍如何监控 Javc GC 行为,同时涉及一些GUI工具的使用(虽然有些已经很老并不再更新),监控GC在于判断JVM ...

随机推荐

  1. rapidxml使用

    以前都是用tinyxml,这次开发中解析xml配置文件像尝试一下rapidxml,据说效率很高... RapidXml Manual: http://rapidxml.sourceforge.net/ ...

  2. UVA 11294 Wedding(2-sat)

    2-sat.不错的一道题,学到了不少. 需要注意这么几点: 1.题目中描述的是有n对夫妇,其中(n-1)对是来为余下的一对办婚礼的,所以新娘只有一位. 2.2-sat问题是根据必然性建边,比如说A与B ...

  3. codevs 1135 选择客栈

    这题没什么话说. #include<iostream> #include<cstdio> #include<cstring> #include<algorit ...

  4. unsigned 和 signed

    http://www.cnblogs.com/stonehat/archive/2011/10/14/2212141.html http://m.blog.csdn.net/blog/u0100862 ...

  5. 理清javascript的相关概念 DOM和BOM

    javascript 有三部分构成,ECMAScript,DOM和BOM,根据宿主(浏览器)的不同,具体的表现形式也不尽相同,ie和其他的浏览器风格迥异.JavaScript=语法+BOM(含DOM) ...

  6. 保护眼睛,开启浏览器的夜间模式 顺便学下!important的作用

    打开笔记本程序,复制以下代码 *{background-image: none !important; background: none !important; background:#333333 ...

  7. cgroup隔离的知识点

    tasks中写入的是线程号 cgroup.procs是进程号 ===================CPU隔离===================== 主机CPU核数: cat /proc/cpui ...

  8. HDU 5389 Zero Escape

    题意:有一些人,每人拿一个号码,有两个门,门的值分别为A和B,要求把人分成两堆(可以为空)一堆人手持号码之和的数字根若等于A或者B就可以进入A门或者B门,要求两堆人分别进入不同的门,求有几种分配方式, ...

  9. hdu 4081 Qin Shi Huang's National Road System(最小生成树+dp)2011 Asia Beijing Regional Contest

    同样是看别人题解才明白的 题目大意—— 话说秦始皇统一六国之后,打算修路.他要用n-1条路,将n个城市连接起来,并且使这n-1条路的距离之和最短.最小生成树是不是?不对,还有呢.接着,一个自称徐福的游 ...

  10. Permutations java实现

    Given a collection of numbers, return all possible permutations. For example,[1,2,3] have the follow ...