引言:JVM提供了诸多的参数进行JVM各个方面内存大小的设置,为Java应用进行优化提供了诸多的工具,本文将会详细分析各个参数的功能与使用。

1.  内存大小-Xmx/-Xms

使用示例:  -Xmx20m -Xms5m

说明: 当下Java应用最大可用内存为20M, 最小内存为5M

代码测试1:

public class JVMTest {public static void main(String[] args) {System.out.print("Xmx=");System.out.println(Runtime.getRuntime().maxMemory()/1024.0/1024+"M");System.out.print("free mem=");System.out.println(Runtime.getRuntime().freeMemory()/1024.0/1024+"M");System.out.print("total mem=");System.out.println(Runtime.getRuntime().totalMemory()/1024.0/1024+"M");}
}

程序执行结果:

大家可以发现,这里打印出来的Xmx值和设置的值之间是由差异的,total Memory和最大的内存之间还是存在一定差异的,就是说JVM一般会尽量保持内存在一个尽可能底的层面,而非贪婪做法按照最大的内存来进行分配。

在测试代码中新增如下语句,申请内存分配:

 byte[] b=new byte[4*1024*1024];System.out.println("分配了1M空间给数组");

程序运行结果:

在申请分配了4m内存空间之后,total memory上升了,同时可用的内存也上升了,可以发现其实JVM在分配内存过程中是动态的, 按需来分配的。

2.  各个代系之间的大小设置

  • -Xmn新生代的设置
  • -XX:NewRatio新生代和年老代的比例; 4表示年轻代:年老代=1:4, 即年轻代占堆的1/5.
  • -XX:SurvivorRatio新生代内部Survivor和Eden区域的比例; 示例: 8表示两个Survivor:Eden=2:8, 即一个Survivor占1/10的新生代空间

代码示例:

JVM的设置为: -Xmx20m -Xms20m -Xmn1m  -XX:+PrintGCDetails

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

结果输出:

[GC (Allocation Failure) [PSYoungGen: 512K->488K(1024K)] 512K->488K(19968K), 0.0014737 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Xmx=19.5M
free mem=8.774787902832031M
total mem=19.5M
HeapPSYoungGen      total 1024K, used 747K [0x00000000ffe80000, 0x0000000100000000, 0x0000000100000000)eden space 512K, 50% used [0x00000000ffe80000,0x00000000ffec0fa8,0x00000000fff00000)from space 512K, 95% used [0x00000000fff00000,0x00000000fff7a020,0x00000000fff80000)to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)ParOldGen       total 18944K, used 10240K [0x00000000fec00000, 0x00000000ffe80000, 0x00000000ffe80000)object space 18944K, 54% used [0x00000000fec00000,0x00000000ff6000a0,0x00000000ffe80000)Metaspace       used 2546K, capacity 4486K, committed 4864K, reserved 1056768Kclass space    used 279K, capacity 386K, committed 512K, reserved 1048576K
Java HotSpot(TM) 64-Bit Server VM warning: NewSize (1536k) is greater than the MaxNewSize (1024k). A new max generation size of 1536k will be used.

结果分析:

由于内存申请大小为1M, 故年轻代无法满足需求,所以10m的内存分配都放到了年老代。这里发生了一次GC,一个内存分配失败,在年轻代中。

关注一下Hotspot的Warning信息,这个提示由于年轻带比较小,故其将其设置了一个NewSize, 较大的值1536k,而非JVM参数中设置的1M大小。

代码示例2:

JVM参数设置: -Xmx20m -Xms20m -Xmn15m  -XX:+PrintGCDetails
      GC输出结果:

Xmx=18.5M
free mem=7.484504699707031M
total mem=18.5M
HeapPSYoungGen      total 13824K, used 11525K [0x00000000ff100000, 0x0000000100000000, 0x0000000100000000)eden space 12288K, 93% used [0x00000000ff100000,0x00000000ffc417f8,0x00000000ffd00000)from space 1536K, 0% used [0x00000000ffe80000,0x00000000ffe80000,0x0000000100000000)to   space 1536K, 0% used [0x00000000ffd00000,0x00000000ffd00000,0x00000000ffe80000)ParOldGen       total 5120K, used 0K [0x00000000fec00000, 0x00000000ff100000, 0x00000000ff100000)object space 5120K, 0% used [0x00000000fec00000,0x00000000fec00000,0x00000000ff100000)Metaspace       used 2542K, capacity 4486K, committed 4864K, reserved 1056768Kclass space    used 279K, capacity 386K, committed 512K, reserved 1048576K

结果分析: 没有发生分配失败和GC回收。 10M的分配都进入了Eden区域。 年老代中为0, Survivior区域为0.
   代码示例3:

JVM参数设置:-Xmx20m -Xms20m -Xmn7m  -XX:+PrintGCDetails

GC结果输出:

[GC (Allocation Failure) [PSYoungGen: 5962K->488K(6656K)] 5962K->1592K(19968K), 0.0013317 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Xmx=19.5M
free mem=12.827682495117188M
total mem=19.5M
HeapPSYoungGen      total 6656K, used 5790K [0x00000000ff900000, 0x0000000100000000, 0x0000000100000000)eden space 6144K, 86% used [0x00000000ff900000,0x00000000ffe2d8d8,0x00000000fff00000)from space 512K, 95% used [0x00000000fff00000,0x00000000fff7a020,0x00000000fff80000)to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)ParOldGen       total 13312K, used 1104K [0x00000000fec00000, 0x00000000ff900000, 0x00000000ff900000)object space 13312K, 8% used [0x00000000fec00000,0x00000000fed14010,0x00000000ff900000)Metaspace       used 2543K, capacity 4486K, committed 4864K, reserved 1056768Kclass space    used 279K, capacity 386K, committed 512K, reserved 1048576K

结果分析:

发生了GC回收,年轻代中回收了将近5M内存,整体占用内存是19M,包括(年轻代和年老代), 用时0.001秒

代码示例4:

JVM参数设置: -Xmx20m -Xms20m -Xmn7m   -XX:SurvivorRatio=2 -XX:+PrintGCDetails
       结果输出:

[GC (Allocation Failure) [PSYoungGen: 3882K->1512K(5632K)] 3882K->1600K(18944K), 0.0013471 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 4664K->1520K(5632K)] 4752K->1656K(18944K), 0.0012496 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 4663K->1496K(5632K)] 4799K->1632K(18944K), 0.0061350 secs] [Times: user=0.05 sys=0.00, real=0.01 secs]
Xmx=18.5M
free mem=15.833610534667969M
total mem=18.5M
HeapPSYoungGen      total 5632K, used 2676K [0x00000000ff900000, 0x0000000100000000, 0x0000000100000000)eden space 4096K, 28% used [0x00000000ff900000,0x00000000ffa27268,0x00000000ffd00000)from space 1536K, 97% used [0x00000000ffd00000,0x00000000ffe76040,0x00000000ffe80000)to   space 1536K, 0% used [0x00000000ffe80000,0x00000000ffe80000,0x0000000100000000)ParOldGen       total 13312K, used 136K [0x00000000fec00000, 0x00000000ff900000, 0x00000000ff900000)object space 13312K, 1% used [0x00000000fec00000,0x00000000fec22000,0x00000000ff900000)Metaspace       used 2542K, capacity 4486K, committed 4864K, reserved 1056768Kclass space    used 279K, capacity 386K, committed 512K, reserved 1048576K

结果分析:

这里SurvivorRatio=2, 表示 2Survior: Eden = 2;2, 这里计算的值不是完全按照1:1来设置的,具体原因未知, 3:4 的结果。 但是设置到10m的时候,就是2:2来走的,这里的可能原因是小数点的值取舍。

发了3次GC,都是发生在新生代。

代码示例5:

JVM参数: -Xmx20m -Xms20m -XX:NewRatio=1   -XX:SurvivorRatio=2 -XX:+PrintGCDetails
     结果输出:

[GC (Allocation Failure) [PSYoungGen: 4932K->1608K(7680K)] 4932K->1616K(17920K), 0.0750661 secs] [Times: user=0.08 sys=0.00, real=0.08 secs]
[GC (Allocation Failure) [PSYoungGen: 5804K->1576K(7680K)] 5812K->1584K(17920K), 0.0223095 secs] [Times: user=0.03 sys=0.00, real=0.02 secs]
Xmx=17.5M
free mem=13.863265991210938M
total mem=17.5M
HeapPSYoungGen      total 7680K, used 3818K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)eden space 5120K, 43% used [0x00000000ff600000,0x00000000ff830af0,0x00000000ffb00000)from space 2560K, 61% used [0x00000000ffd80000,0x00000000fff0a030,0x0000000100000000)to   space 2560K, 0% used [0x00000000ffb00000,0x00000000ffb00000,0x00000000ffd80000)ParOldGen       total 10240K, used 8K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)object space 10240K, 0% used [0x00000000fec00000,0x00000000fec02000,0x00000000ff600000)Metaspace       used 2542K, capacity 4486K, committed 4864K, reserved 1056768Kclass space    used 279K, capacity 386K, committed 512K, reserved 1048576K

结果分析:

NewRatio为1, 则新生代和年老代的比例是1:1, 都为10M。 SurvivorRatio为2, 则2个survior:eden = 2:2, 平均分配, 5m, 2.5m, 2.5m.

发生了两次GC操作。分别回收了大约3m和4m的内存空间。

代码示例6:

JVM参数:-Xmx20m -Xms20m -XX:NewRatio=1   -XX:SurvivorRatio=3 -XX:+PrintGCDetails
    结果输出:

[GC (Allocation Failure) [PSYoungGen: 5962K->1656K(8192K)] 5962K->1664K(18432K), 0.0025830 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Xmx=18.0M
free mem=11.257377624511719M
total mem=18.0M
HeapPSYoungGen      total 8192K, used 6958K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)eden space 6144K, 86% used [0x00000000ff600000,0x00000000ffb2d8e0,0x00000000ffc00000)from space 2048K, 80% used [0x00000000ffc00000,0x00000000ffd9e020,0x00000000ffe00000)to   space 2048K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x0000000100000000)ParOldGen       total 10240K, used 8K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)object space 10240K, 0% used [0x00000000fec00000,0x00000000fec02000,0x00000000ff600000)Metaspace       used 2542K, capacity 4486K, committed 4864K, reserved 1056768Kclass space    used 279K, capacity 386K, committed 512K, reserved 1048576K

结果分析:

出现了一次内存分配失败,年轻代发生了一次GC回收,回收了将近4M空间。这次修改SurviorRatio的比例,将Eden区域放大,由于其分配的空间为1m左右,则会降低GC的发生次数。

3. 堆的分配参数设置

  • -XX:+HeapDumpOnOutOfMemoryError  OOM之时导出堆镜像到文件
  • -XX:+HeapDumpPath  导出OOM文件的路径设置
  • -XX:OnOutOfMemoryError 在OOM时,执行一个脚本

示例如下:-XX:OnOutOfMemoryError=D:/tools/jdk1.7_40/bin/printstack.bat %p   在发生OOM之时,发送邮件或者重启应用等动作。

代码示例:

import java.util.ArrayList;
import java.util.Listpublic class OOMTest {public static void main(String[] args) {List<Object> refs = new ArrayList<Object>();for (int i=0; i<25; i++) {refs.add(new byte[1*1024*1024]);}}
}

JVM参数设置:   -XX:+HeapDumpOnOutOfMemoryError -XX:+HeapDumpPath=d:\oom.dump

结果输出:

java.lang.OutOfMemoryError: Java heap space
Dumping heap to d:\oom.dump ...
Heap dump file created [14814170 bytes in 0.022 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceat org.homework.test.jvm.jvmopt.OOMTest.main(OOMTest.java:12)

Dump文件的位置在D盘的oom.dump,文件大小为14m,一般这类文件的打开需要使用visualvm之类来进行。

打开JDK的安装路径,在bin目录下即可发现visualvm的可程序程序:

基于visualvm打开dump文件,发现问题所在原因,是由于byte申请占用太多的空间,达到98%的内容。

3. 总结

一般情况下,需要根据实际的情况而定来决定其比例和大小;记得在生产应用记得配置OOM的设置,确保在OOM情况下,可以将当时的堆文件镜像转储到本地文件。或者可以配置触发事件,确保发送OOM,可以通知相关方及时采取措施进行处理。

官方推荐新生代占堆的3/8,幸存代占新生代的1/10。

JVM内存设置参数分析相关推荐

  1. JVM内存配置参数、GC工作原理及Minor GC、FullGC

    对于JVM内存配置参数: -Xmx10240m -Xms10240m -Xmn5120m -XXSurvivorRatio=3 -Xms10240m 初始堆大小即最小内存值 XXSurvivorRat ...

  2. 全面认识Eclipse中JVM内存设置

        这里向大家描述一下Eclipse中如何进行JVM内存设置,JVM主要管理两种类型的内存:堆和非堆.简单来说堆就是Java代码可及的内存,是留给开发人员使用的:非堆就是JVM留给自己用的,所以方 ...

  3. 全面认识Eclipse中JVM内存设置(转)

    这里向大家描述一下Eclipse中如何进行JVM内存设置,JVM主要管理两种类型的内存:堆和非堆.简单来说堆就是Java代码可及的内存,是留给开发人员使用的:非堆就是JVM留给自己用的,所以方法区.J ...

  4. jvm内存配置参数_性能测试连载 (23)jvm内存参数设置

    概述 java内存溢出之后,我们需要根据错误信息分析一下内存溢出的具体原因,及时调整中间件的参数. 查看jvm内存分配 linux下可以通过jmap -heap [pid]命令查看jvm的内存分配 例 ...

  5. JVM参数汇总:JVM内存设置多大合适?Xmx和Xmn如何设置

    一.java启动参数共分为三类: 其一是标准参数(-), 所有的JVM实现都必须实现这些参数的功能,而且向后兼容: 其二是非标准参数(-X), 默认jvm实现这些参数的功能,但是并不保证所有jvm实现 ...

  6. 生产环境 JVM 内存溢出案例分析

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 来源:blog.csdn.net/prestigeding ...

  7. 生产环境JVM内存溢出案例分析

    如果我们所在公司的业务量比较大,在生产环境经常会出现JVM内存溢出的现象,那我们该如何快速响应,快速定位,快速恢复问题呢? 本文将通过一个线上环境JVM内存溢出的案例向大家介绍一下处理思路与分析方法. ...

  8. 生产环境JVM内存溢出案例分析!

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:Nginx 为什么快到根本停不下来? 个人原创100W+访问量博客:点击前往,查看更多 来源:blog.csdn ...

  9. jvm 内存查看与分析工具

    转自http://jameswxx.iteye.com/blog/731763 业界有很多强大的java profile的工具,比如Jporfiler,yourkit,这些收费的东西我就不想说了,想说 ...

  10. 流计算 Oceanus | Flink JVM 内存超限的分析方法总结

    作者:董伟柯,腾讯 CSIG 高级工程师 问题背景 前段时间,某客户线上运行的大作业(并行度 200 左右)遇到了 TaskManager JVM 内存超限问题(实际内存用量 4.1G > 容器 ...

最新文章

  1. 使用Javascript制作连续滚动字幕
  2. windows下安装pygtk报g_assertion_message无法定位libglib-2.0-0.dll错误解决
  3. 【Matlab】怎么判断两个字符串相等?
  4. 两次深度debug经历,希望大家不要踩坑
  5. Github 15K! 亿级向量相似度检索库Faiss 原理+应用
  6. postgresql-9.6.6主从
  7. android的简单知识,Android基础知识(简单实例计算器)
  8. 小趣味:js编写斗地主规则(完整代码)
  9. git clone报错error: RPC failed; curl 56 GnuTLS recv error (-110): The TLS connection was non-properly
  10. 计算机专业哪个考研简单,考研哪些专业比较简单好考?
  11. OMV搭建系列教程[5] – 安装Aria2
  12. 搭配Online:瑞幸昔日“盟友”神州优车,与北汽集团达成战略合作
  13. 深入浅出讲解 Python 元类(Metaclass)的使用
  14. Three.js-光线投射(raycaster)
  15. 笨办法学Python 25
  16. MySQL自定义函数和存储过程
  17. 计算机主机配置讲解,组装机电脑配置单讲解
  18. 数字信号处理4:采样定理
  19. AS608 指纹模块驱动代码
  20. 图文结合纯c手写内存池

热门文章

  1. CCF 201703-5 引水入城
  2. 固态硬盘装win7系统怎么安装教程
  3. 基于videojs 实现javascript弹幕功能
  4. contextual Attention
  5. win10计算机联接多个网络,win10两台电脑连接局域网的详细操作教程
  6. 一台计算机连接两个投影,一台电脑两个投影仪要如何连接
  7. 程序猿来找找自己的目标
  8. 三流大学和一流大学学生的简历有什么区别?
  9. 波士顿动力SpotMini改造有胳膊半人马,这家意大利创企打造极致机械手臂
  10. matlab中时域逐步积分方法,newmark积分法