`
龙飞凤舞的程序员
  • 浏览: 1187 次
  • 性别: Icon_minigender_1
文章分类
社区版块
存档分类
最新评论

跟我一起來研究Java内存管理

 
阅读更多

先看下面这个小程序

/**
 * 这个小程序作用是创建一个大约1MB的对象
 * 以下参数为运行设置中的VM Arguments参数
 * -verbose:gc
 * -XX:+PrintGCDetails
 * -Xms20M 
 * -Xmx20M
 * -Xmn10M
 * @author qianl
 *
 */
public class Test {

	public static int _1M = 1024 * 1024;
	
	public static void main(String[] args) throws InterruptedException {
		byte[] b1;
		b1 = new byte[1 * _1M];
	}

}

先解释一下VM Arguments参数:
* -verbose:gc : 输出GC的详细信息
* -XX:+PrintGCDetails : 打印GC工作的内存变化详细信息
* -Xms20M : 堆最小值
* -Xmx20M : 堆最大值
* -Xmn10M : 分配给新生代区(后面将会讲解)的大小

下面是运行后,控制台的输出:


如果英文不好,看着费劲的,下面我照着翻译一下

接下来,我们一起來分析一下

在VM Arguments设置中,我们将堆总空间设置为20M,且不可扩展,其中10M分给新生代,剩余10M分给了老年代。可能有个疑问了,中间的 “PSOldGen total 10240K”,确实刚好有10M,可是,这一句 “PSYoungGen total 8960K, used 1485K” ,哪有10M。大家看这一句下面的信息,eden的7680K,from space的1280K,to space的1280K,这三个加起来,是不是刚好10240K = 10M呢。

这里面有个细节,新生代大小,具体指的是一个eden区加上一个Survivor(就是上面的from space和to space)区。我们给新生代分配的10M,实际上是分给了三个区域,一个eden区和两个Survivor区,从数字可以看出,它们默认的分配比例为8:1:1,当然,可以手动设置的,感兴趣的可以自己查一下。所以上面中,新生代的total为8960K(eden:7680K,Survivor:1280K)。
PS : 我在网上看了一下,对于Survivor还有另外一种解释,from space和to space共同构成Survivor区,eden和Survivor构成新生代区,如果这样,那么PSYoungGen(新生代区)就应该是10240K,但实际PSYoungGen只有8960K,它没算上to space区。至于那种好,各位因人而异吧。

这里解释一下这三个区的区别:
* PSYoungGen : 主要存放新生的对象
* PSOldGen : 主要存放应用程序中生命周期长的对象
* PSPermGen : 永久保存区,方法区(参见我的另外一篇《Java虚拟机内存管理》)的对象放置在此区域

那么,Java虚拟机,是怎样安排放置对象到这些区域的呢?将上面的程序改一下:

/**
 * 此程序创建了两个大约7M的对象
 * 以下参数为运行设置中的VM Arguments参数
 * -verbose:gc
 * -XX:+PrintGCDetails
 * -Xms20M 
 * -Xmx20M
 * -Xmn10M
 * @author qianl
 *
 */
public class Test {

	public static int _1M = 1024 * 1024;

	
	public static void main(String[] args) throws InterruptedException {
		byte[] b1,b2;
		b1 = new byte[7 * _1M];
		b2 = new byte[7 * _1M];
	}

}

控制台输出为:

从控制台输出的信息,可以看出,当第一个对象b1创建了一个7M对象时,首先会考虑到新生代的eden区,如果空间够,就会放置在此,可以看出上面的eden差不多刚好放下7M的对象,使用率占了99%。
当下面的b2创建时,发现eden区域不够了,这是,Java虚拟机就会把对象放置到老年代区域中,从上面可以看到,PSOldGen使用率为70%。

故,从这个实验,可以得出结论,对象优先在eden区存放,如果eden区域空间不够,就是放置在老年代区域中。如果两个都不够,将报错:java.lang.OutOfMemoryError: Java heap space

下面,咱们來验证长期存活的对象,将进入老年代。

什么才算是长期存货的对象呢?在Java虚拟机中,给每个对象定义了一个对象年龄计数器,如果对象在eden出生并经过GC后仍然存活,并能被Survivor容纳,被移动到Survivor空间中,那么它的年龄就加1.当年龄到一定程度(默认为15岁)时,就会被移到老年代中。其中,晋升年龄的年龄,可以通过 -XX:MaxTenuringThreshold 來设置,下面,我们通过设置它为1,來做这个实验。如下代码所示:

/**
 * 以下参数为运行设置中的VM Arguments参数
 * -verbose:gc
 * -XX:+PrintGCDetails
 * -Xms20M 
 * -Xmx20M
 * -Xmn10M
 * -XX:MaxTenuringThreshold=1
 * @author qianl
 *
 */
public class Test {

	public static int _1M = 1024 * 1024;

	
	public static void main(String[] args) throws InterruptedException {
		byte[] b1,b2;
		b1 = new byte[2 * _1M];
		b2 = new byte[2 * _1M];
		b2 = null;
		System.gc(); //使b2其经过一次GC操作
		b2 = new byte[2 * _1M]; //年龄长为1,将近入老年代区域
	}

}

控制台输出:

上述第一句Full GC...说明经过一次GC操作。
由控制台的信息,可以看到PSOldGen使用了2164K,这是由于我们将年龄判断值设为1,上面程序中,b2经过我们手动操作,年龄变为了1,于是移动到了老年代中。大家可以自己将-XX:MaxTenuringThreshold设置大些,或者不设置,看PSOldGen区域会不会被使用,本人已做过实验,证明是正确的,大家可以自己做一下。

实际上,还有一种情况,Java虚拟机会动态判定对象年龄。
如果在Survivor空间中,相同年龄的所有对象大小总和,大于Survivor空间的一半,大于或等于这个年龄的对象,就可以直接进入老年代。这个,大家也可以自行下去做下实验验证。


分享到:
评论

相关推荐

    操作系统(内存管理)

    在很多脚本语言中,您不必担心内存是如何管理的,这并不能使得内存管理的重要性有一点点降低。对实际编程来说,理解您的内存管理器的能力与局限性至关重要。在大部分系统语言中,比如 C 和 C++,您必须进行内存管理...

    java开源包101

    MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的Java包,主要特点是多线程、调度、JMX管理和批量执行报表,执行历史等。 SIP协议包 jSIP.tar jSIP这个Java包目标是用Java实现SIP(SIP:...

    精品:java虚拟机分析与优化PPT

    我们将分析它是如何进行垃圾回收,内存管理,堆压缩,以及其他高级特性。我们还将研究如何配置JVM使得性能得以最优化。演讲者将列出对于IBM和SUN JVM在1.4.2以及1.5版本上对WebSphere有用的一组调优参数。如果您对...

    高级java笔试题-understanding-the-jvm:《深入理解Java虚拟机》阅读笔记

    内存管理机制和 Java 虚拟机程序执行需要重点掌握,并且内容也是比较多的。本 repo 将原书中有关虚拟机性能监控及故障处理的部分单抽了出来,组成了本 repo 的第三部分。第四部分对应于原书的第四部分,程序编译与...

    毕业设计---基于java坦克大战课程设计报告.doc

    需求分析 通过反复研究以及市场调查,得知游戏须具有以下功能: 需要有图形游戏界面,让用户能看到游戏给出的反馈 有人机交互功能,使用户能操作指定的游戏元素 不同队伍的坦克,须显示不同外观,已分辨敌我 坦克...

    二十三种设计模式【PDF版】

    很简单一个模式,就是在内存中保留原来数据的拷贝. 设计模式之 Interpreter(解释器) 主要用来对语言的分析,应用机会不多. 设计模式之 Visitor(访问者) 访问者在进行访问时,完成一系列实质性操作,而且还可以扩展. ...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    与我一同工作的同志对本研究所做的任何贡献均已在论文中作了明确的说明并表示了谢意。 研究生签名: 日期: 东南大学学位论文使用 授权声明 东南大学、中国科学技术信息研究所、国家图书馆有权保留本人...

    windows 程序设计

    Kernel(日前由16位的KRNL386.EXE和32位的KERNEL32.DLL实现)处理所有在传统上由操作系统核心处理的事务-内存管理、文件I/O和多任务管理。User(由16位的USER.EXE和32位的USER32.DLL实作)指使用者接口,实作所有...

    大数据基础知识入门.pdf

    麦肯锡全球研究所给出的定义是:一 种规模大到在获取、存储、管理、分 析方面大大超出了传统数据库软件工 具能力范围的数据集合,具有海量的 数据规模、快速的数据流转、多样的 数据类型和价值密度低四大特征。...

    C语言入门经典(第4版)--源代码及课后练习答案

     杨浩,知名译者,大学讲师,从事机械和计算机方面的教学和研究多年,发表论文数篇,参编和翻译的图书多达20余部,还曾多次获得市部级奖项。近几年一直在跟踪.NET技术的发展,积极从事.NET技术文档和图书的翻译工作...

    Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐)--随书源代码

     KAREN MORTON 研究人员、教育家及顾问,Fidelity信息服务公司的资深数据库管理员和性能调优专家。她从20世纪90年代初就开始使用Oracle,从事 Oracle的教学工作也已经超过10年的时间。她是Oracle ACE,也是...

    Cocos2D-X游戏开发技术精解

    7.7.2 内存管理机制 207 7.7.3 工厂模式 208 7.7.4 数据单位 208 7.7.5 用户数据 209 7.8 物理世界World 210 7.8.1 创建和摧毁一个世界 210 7.8.2 让世界运转起来 211 7.8.3 探索世界 212 7.8.5 AABB查询 ...

Global site tag (gtag.js) - Google Analytics