jvm java虚拟机 新生代的配置

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

1.1.1.1. -Xmn参数

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

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

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

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

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

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

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

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)

设置的edenfrom的比例是2:1 from=to 这里前面说过,输出也确实证明是相等的。所以eden512K,新生代我们分配的是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内存,所以运行的时候产生了3GC垃圾回收,因为程序申请内存的时候,变量失去了上一次的引用指针。所以是在新生代中进行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可以设置老年代新生代的比例。

完成的公式如下图所示:




相关文章
|
24天前
|
监控 算法 Java
Java虚拟机(JVM)的垃圾回收机制深度解析####
本文深入探讨了Java虚拟机(JVM)的垃圾回收机制,旨在揭示其背后的工作原理与优化策略。我们将从垃圾回收的基本概念入手,逐步剖析标记-清除、复制算法、标记-整理等主流垃圾回收算法的原理与实现细节。通过对比不同算法的优缺点及适用场景,为开发者提供优化Java应用性能与内存管理的实践指南。 ####
|
15天前
|
监控 算法 Java
Java虚拟机(JVM)垃圾回收机制深度剖析与优化策略####
本文作为一篇技术性文章,深入探讨了Java虚拟机(JVM)中垃圾回收的工作原理,详细分析了标记-清除、复制算法、标记-压缩及分代收集等主流垃圾回收算法的特点和适用场景。通过实际案例,展示了不同GC(Garbage Collector)算法在应用中的表现差异,并针对大型应用提出了一系列优化策略,包括选择合适的GC算法、调整堆内存大小、并行与并发GC调优等,旨在帮助开发者更好地理解和优化Java应用的性能。 ####
24 0
|
12天前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
15天前
|
存储 监控 算法
Java虚拟机(JVM)垃圾回收机制深度解析与优化策略####
本文旨在深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法及参数调优方法。通过剖析垃圾回收的生命周期、内存区域划分以及GC日志分析,为开发者提供一套实用的JVM垃圾回收优化指南,助力提升Java应用的性能与稳定性。 ####
|
18天前
|
机器学习/深度学习 监控 算法
Java虚拟机(JVM)的垃圾回收机制深度剖析####
本文深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法、性能调优策略及未来趋势。通过实例解析,为开发者提供优化Java应用性能的思路与方法。 ####
31 1
|
19天前
|
Oracle 安全 Java
深入理解Java生态:JDK与JVM的区分与协作
Java作为一种广泛使用的编程语言,其生态中有两个核心组件:JDK(Java Development Kit)和JVM(Java Virtual Machine)。本文将深入探讨这两个组件的区别、联系以及它们在Java开发和运行中的作用。
39 1
|
23天前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
190 1
|
2月前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
40 4
|
21天前
|
Java
JVM内存参数
-Xmx[]:堆空间最大内存 -Xms[]:堆空间最小内存,一般设置成跟堆空间最大内存一样的 -Xmn[]:新生代的最大内存 -xx[use 垃圾回收器名称]:指定垃圾回收器 -xss:设置单个线程栈大小 一般设堆空间为最大可用物理地址的百分之80
|
22天前
|
Java
JVM运行时数据区(内存结构)
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一 (3)程序计数器:保存指令执行的地址,方便线程切回后能继续执行代码
19 3