jvm java虚拟机 新生代的配置

版权声明:本文为博主原创文章,未经博主允许不得转载。不经过允许copy,讲追究法律责任,欢迎加入我们的学习提升群523988350,可以相互交流

目录(?)[+]

  1. 111 -Xmn参数
  2. 112 第一种情况-Xmx20m -Xms20m -Xmn1m -XXSurvivorRatio2 -XXPrintGCDetails
  3. 113 第二种情况-Xmx20m -Xms20m -Xmn7m -XXSurvivorRatio2 -XXPrintGCDetails
  4. 114 第三种情况-Xmx20m -Xms20m -Xmn15m -XXSurvivorRatio8 -XXPrintGCDetails
  5. 115 -XXNewRatio参数
  6. 116 第四种情况-Xmx20m -Xms20m  -XXNewRatio2 -XXPrintGCDetails

1.1.1.1. -Xmn参数

参数-Xmn1m可以用于设置新生代的大小。设置一个较大的新生代会影响老生代的大小,因为这两者的总和是一定的,这个系统参数对于系统性能以及GC行为有很大的影响,新生代一般设置为整个堆空间的1/3到1/4左右最合适。

参数-XX:SurvivorRatio用来设置新生代中eden空间和from/to空间的比例,公式如下:

-XX:SurvivorRatio=eden/from =eden/to

解释:from和to之间的两块区间内存是相等的。可以参考

java虚拟机 jvm java堆 方法区 java栈这篇文章,下面的输出也会印证from和to之间的两块区间内存是相等的。

使用不同的堆分配参数确实有很大的影响,下面开始验证影响。

下面代码是循环十次每次申请1M的空间一共申请10M,代码如下:

[java] view plain copy print?

  1. byte[] b = null;
  2. for (int i = 0; i < 10; i++) {
  3. b = new byte[1 * 1024 * 1024];
  4. }

byte[] b = null;
for (int i = 0; i < 10; i++) {
b = new byte[1 * 1024 * 1024];
}

1.1.1.2. 第一种情况:-Xmx20m -Xms20m -Xmn1m -XX:SurvivorRatio=2 -XX:+PrintGCDetails

配置上面的参数程序的输出如下:

[GC [DefNew: 512K->256K(768K), 0.0010949 secs] 512K->377K(20224K), 0.0011182 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

Heap

def new generation   total 768K, used 488K [0x335d0000, 0x336d0000, 0x336d0000)

  eden space 512K,  45% used [0x335d0000, 0x3360a2e0, 0x33650000)

from space 256K,100% used [0x33690000, 0x336d0000, 0x336d0000)

  to   space 256K,  0% used [0x33650000, 0x33650000, 0x33690000)

 tenured generation   total 19456K, used 10361K[0x336d0000, 0x349d0000, 0x349d0000)

the space 19456K,  53% used [0x336d0000, 0x340ee730, 0x340ee800, 0x349d0000)

compacting perm gen  total 12288K, used 146K [0x349d0000, 0x355d0000, 0x389d0000)

the space 12288K,   1% used [0x349d0000, 0x349f4a58, 0x349f4c00, 0x355d0000)

ro space 10240K,  45% used [0x389d0000, 0x38e59b28, 0x38e59c00, 0x393d0000)

rw space 12288K,  54% used [0x393d0000, 0x39a5d0e8, 0x39a5d200, 0x39fd0000)

设置的eden与from的比例是2:1 from=to 这里前面说过,输出也确实证明是相等的。所以eden为512K,新生代我们分配的是1M=512K+256K+256k=1024K=1M,总的可用的新生代为512K+256K=768K;

由于新生代的eden区域的内存为512K,我们每次申请的空间是1M,所以没有办法容纳,因此触发了一次GC垃圾回收,对eden区域的内存进行了部分的回收,新生代没有内存容纳1M的内存还是不够存储,所以数组都被分配到老生代,老生代最终占用了10361K空间。

1.1.1.3. 第二种情况:-Xmx20m -Xms20m -Xmn7m -XX:SurvivorRatio=2 -XX:+PrintGCDetails

第二种情况将新生代内存扩大到7M,输出如下:

[GC [DefNew: 2795K->1498K(5376K), 0.0018315 secs] 2795K->1498K(18688K), 0.0018637 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

[GC [DefNew: 4687K->1024K(5376K), 0.0011140 secs] 4687K->1498K(18688K), 0.0011327 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

[GC [DefNew: 4125K->1024K(5376K), 0.0004712 secs] 4599K->1498K(18688K), 0.0004903 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

Heap

def new generation   total 5376K, used 3163K [0x335d0000, 0x33cd0000, 0x33cd0000)

  eden space 3584K, 59% used [0x335d0000, 0x337e6d38, 0x33950000)

  from space 1792K, 57% used [0x33b10000, 0x33c10010, 0x33cd0000)

  to   space 1792K,  0% used [0x33950000, 0x33950000, 0x33b10000)

 tenured generation   total 13312K, used 474K[0x33cd0000, 0x349d0000, 0x349d0000)

the space 13312K,   3% used [0x33cd0000, 0x33d468e0, 0x33d46a00, 0x349d0000)

compacting perm gen  total 12288K, used 146K [0x349d0000, 0x355d0000, 0x389d0000)

the space 12288K,   1% used [0x349d0000, 0x349f4a58, 0x349f4c00, 0x355d0000)

ro space 10240K,  45% used [0x389d0000, 0x38e59b28, 0x38e59c00, 0x393d0000)

rw space 12288K,  54% used [0x393d0000, 0x39a5d0e8, 0x39a5d200, 0x39fd0000)

在这个参数下eden的内存为3584K,所以可以有空间存储数组,所以数组先被分配到这个eden区,但是还不能完全预留全部的10M内存,所以运行的时候产生了3次GC垃圾回收,因为程序申请内存的时候,变量失去了上一次的引用指针。所以是在新生代中进行GC垃圾回收。最终的结果:所有的内存都被分配到新生代进行,通过GC保证了新生代有足够的空间存储。而没有进入老年代,只是在GC过程中,部分新生对象晋升到老年代。

 

1.1.1.4. 第三种情况:-Xmx20m -Xms20m -Xmn15m -XX:SurvivorRatio=8 -XX:+PrintGCDetails

第三种情况将新生代内存扩大到15M,输出如下:

Heap

def new generation   total 13824K, used 11223K [0x335d0000, 0x344d0000, 0x344d0000)

  eden space 12288K,  91% used [0x335d0000, 0x340c5f50, 0x341d0000)

  from space 1536K,  0% used [0x341d0000, 0x341d0000, 0x34350000)

 to   space 1536K,  0% used [0x34350000, 0x34350000, 0x344d0000)

tenured generation   total 5120K, used 0K[0x344d0000, 0x349d0000, 0x349d0000)

the space 5120K,   0% used [0x344d0000, 0x344d0000, 0x344d0200, 0x349d0000)

compacting perm gen  total 12288K, used 146K [0x349d0000, 0x355d0000, 0x389d0000)

the space 12288K,   1% used [0x349d0000, 0x349f4a58, 0x349f4c00, 0x355d0000)

ro space 10240K,  45% used [0x389d0000, 0x38e59b28, 0x38e59c00, 0x393d0000)

rw space 12288K,  54% used [0x393d0000, 0x39a5d0e8, 0x39a5d200, 0x39fd0000)

 

在这次的测试中,新生代被分配15M内存,eden的内存是12288K,所有这个区域完全可以容纳10M的内存数组,所以所有的分配都是在eden直接进行,并没有触发GC垃圾回收,因此from/to和老年代tenured使用率都是0.

通过上面的例子,发现不同的堆分配策略对系统执行的影响还是很大。所以在实际开发中,还是要合理的设置值,基本策略:尽可能将对象预留在新生代,减少老年代GC次数。(第一种情况对象都被分配到老年代,老年代肯定要进行GC垃圾回收)

1.1.1.5. -XX:NewRatio参数

-XX:NewRatio参数主要设置新生代和老年代的比例。公式如下:

-XX:NewRatio=老年代/新生代

1.1.1.6. 第四种情况:-Xmx20m -Xms20m  -XX:NewRatio=2 -XX:+PrintGCDetails

第四种参数设置为:-Xmx20m -Xms20m  -XX:NewRatio=2 -XX:+PrintGCDetails 程序的输出如下:

[GC [DefNew: 4899K->474K(6144K), 0.0016090 secs] 4899K->1498K(19840K), 0.0016426 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

[GC [DefNew: 5768K->0K(6144K), 0.0011308 secs] 6792K->2522K(19840K), 0.0011490 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

Heap

def new generation   total 6144K, used 1134K [0x335d0000, 0x33c70000, 0x33c70000)

  eden space 5504K,  20% used [0x335d0000, 0x336eb8c8, 0x33b30000)

from space 640K,   0% used [0x33b30000, 0x33b30088, 0x33bd0000)

  to   space 640K,   0% used [0x33bd0000, 0x33bd0000, 0x33c70000)

 tenured generation   total 13696K, used 2522K [0x33c70000, 0x349d0000, 0x349d0000)

the space 13696K,  18% used [0x33c70000, 0x33ee6878, 0x33ee6a00, 0x349d0000)

compacting perm gen  total 12288K, used 146K [0x349d0000, 0x355d0000, 0x389d0000)

the space 12288K,   1% used [0x349d0000, 0x349f4a58, 0x349f4c00, 0x355d0000)

ro space 10240K,  45% used [0x389d0000, 0x38e59b28, 0x38e59c00, 0x393d0000)

rw space 12288K,  54% used [0x393d0000, 0x39a5d0e8, 0x39a5d200, 0x39fd0000)

因为堆空间分配的内存为20M,老年代和新生代比例我们设置的是2:1,所以新生代的内存大约是6144K 老年代的内存是13696K。由于新生代Gc的时候,from/to的内存容纳不下任何一个1m数组对象,影响了新生代的正常回收,所以对象都跑到老年代空间了。因此导致两个1MB数组进入老年代,(新生代GC,还有1M数组幸存,按理说应进入from/to但是from/to只有640K空间不足)

注意:

 -XX:SurvivorRatio可以设置eden区与Survivor区比例,-XX:NewRatio可以设置老年代新生代的比例。

完成的公式如下图所示:

时间: 2024-08-07 08:38:43

jvm java虚拟机 新生代的配置的相关文章

JVM(java 虚拟机)

JVM(java 虚拟机) 一.JVM简介 1.JVM:Java Virtual Machine (java 虚拟机) 通过软件来模拟出来的具有完整的硬件系统功能.运行在完全隔离的环境中的完整的计算机系统. 2.种类: 1)Sun Classic 经典款2)Exact VM 准确式内存管理3)Sun HotSpot VM 热代码跟踪 二.JVM运行时的区域 1.运行时的区域 2.线程隔离区域(程序计数器.java栈) 程序计数器:是当前线程所执行的字节码的行号指示器,字节码解释器工作时就是通过改

jvm java虚拟机

jdk jre ==================================== # ./jre1.6.0_27-for-linux.bin # ls /usr/java/jre1.6.0_27/ # mv /usr/java/jre1.6.0_27/* /usr/java/ # vi profile27 export JAVA_HOME=/usr/javaexport PATH=$JAVA_HOME/bin:$PATHexport CLASSPATH=$JAVA_HOME/lib ==

JVM——Java虚拟机架构

版权声明:本文为博主原创文章,未经博主允许不得转载. 0. 前言 Java虚拟机(Java virtualmachine)实现了Java语言最重要的特征:即平台无关性. 平台无关性原理:编译后的 Java程序(.class文件)由 JVM执行.JVM屏蔽了与具体平台相关的信息,使程序可以在多种平台上不加修改地运行.Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行.因此实现Java平台无关性. 本文主要介绍JVM中的架构知识,转载请注明出处:http://blog.csdn.n

JVM——java虚拟机内存结构简介

JAVA虚拟机内存结构示意图 各区域介绍 程序计数器 程序计数器,用来记录每一个线程正在执行的指令地址.每一个线程有一个线程计数器,因此该区域是"线程私有"的内存,生命周期与线程相同.如果线程执行的是native本地方法,则程序计数器为空. 虚拟机栈区 每当线程执行一个方法时,虚拟机就会在这个区域创建一个栈帧,用于存储局部变量.动态链接.方法出口等信息.该区域也是"线程私有"的内存. 本地方法栈 本地方法栈主要是用来执行Native方法服务的 Java堆 所有线程共

java 虚拟机--新生代与老年代GC

Heap: JVM只有一个为所有线程所共享的堆,所有的类实例和数组都是在堆中创建的. Method area: JVM只有一个为所有的线程所共享的方法区.它存储类结构,例如运行时常量池,成员和方法数据以及方法.构造方法的代码. Java Stacks:每个JVM线程拥有一个私有的栈. Pc registers: JVM可以同时支持运行多个线程,因此每个线程需要各自的PC(program counter)寄存器. Native method stacks: 保存native方法进入区域的地址 .

JVM调优-新生代

JAVA虚拟机新生代,包括eden space+2个survivor空间. 新生代用来存放新近创建的对象,新生代的特点是对象更新速度快,在短时间内产生大量的"死亡对象".对年轻代的垃圾回收称作次级回收 (minor gc) 1.新生代与次级回收 新生代分为三个区域,  一个eden spac , 2个大小相同的survivor,  应用程序只能使用一个eden和一个survivor, 当发生初级垃圾回收的时候,gc挂起程序, 然后将eden和survivorA中的存活对象复制到另外一个

java开发前的配置

JAVA语言是1995年由Sun公司退出的一门高级编程语言,在2009年4月20被ORACLE公司收购 看看java体系图 来看看一些专业术语: JVM:JAVA虚拟机 那么JVM是怎么工作的呢.看一幅图 是不是还是不知道什么是编译器.什么是字节码.什么是解释器.好吧.在看一个图片 在看看JDK,JRE JDK:没有JDK就没办法进行java程序的开发 JRE:如果想运行一个java程序.就需要安装JRE 从下图中可以看JDK.JRE.JVM之间的关系,当安装了JDK后.就已经包含了JRE和JV

java 虚拟机原理

什么是JVM JVM是Java Virtual Machine(Java虚拟机)的缩写,是一个虚构出来的计算机,它屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码,ByteCode), 就可以在多种平台上不加修改地运行.这背后其实就是JVM把字节码翻译成具体平台上的机器指令,从而实现"一次编写,到处运行(Write Once, Run Anywhere)". Java为什么能够跨平台? Java引入了字节码的概念,jvm 只能认识字节

java虚拟机底层结构详解[转]

本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 在以前的博客里面,我们介绍了在java领域中大部分的知识点,从最基础的java最基本语法到SSH框架.这里面应该包含了在java领域里面的大部分内容了吧.但是,那些知识点是让我们从一个应用的层面上了解了java,java程序真正底层的运行机制和一些底层虚拟机的工作我们还不了解,虽然这些内容在我们真正的开发中几乎用不到这些底层的东西,但对于我们对java的理解会有比较大的帮助.尤其也对以后