1. JVM Tuning基础知识

1.1 Java堆结构

  Java堆可以处于物理上不连续的内存空间上,只要逻辑上是连续的即可。Java堆就是各种对象分配和保存的内存空间,线程间共享。Java堆分为Eden区,Survivor区,tenured区和Permanent区,如下图所示。

  Java堆的分配原则如下:

  • Java堆分布如下图所示,新的类的实例大部分在Eden(之所以用Eden这个词也就是表示初创起始的意思)区分配。
  • Eden区满的时候,或者需要GC时,依然存活的对象将被复制到Survivor区,一共有两个survivor区,当一个survivor区满时,依然存活的对象将被复制到另一个survivor区。
  • 当survivor区全满时,从第一个survivor区复制过来的,且此时还存活的对象将被复制到Tenured Generation(年老代)
  • Perm Generation用于存放静态文件,持久代大小可以通过MaxPermSize进行设置。

  Perm Generation是JVM的驻留内存,用于存放JDK自身携带的CLASS,Interface的元数据等。被装载进此区域的数据是不会被垃圾回收器GC回收掉的,关闭JVM时,释放此区域所控制的内存。

  Java对象的声明周期在堆中从Young到Tenured,这个期间从Eden诞生到Tenured死亡。当EDEN区不够用时,将触发minor gc,GC会对EDEN区进行垃圾回收,将不再使用的对象进行销毁,同时如果发现对象还被其他对象引用,则将对象移动到survivor区,后面依此类推,当Tenured区发生GC时,称为major gc,由于java中大部分对象的生命周期都很短,所以GC一般发生在Eden区,因此minor gc发生的频率比major gc要高很多。如果最后整个堆空间都满了,则会爆出异常JVM对空间溢出:java.lang.OutOfMemoryError: java heap space。

1.2 JVM GC算法枚举

  • Mark-sweep算法

        即标记回收算法,将需要回收的对象标记,再统一回收。这种算法适合Perm代的对象,以为Perm代的存储空间比较大,需要回收的又不多。

  • Copying算法

     即复制算法,直接拷贝。适合Eden区的对象向survivor区拷贝,因为Eden区的对象大部分都需要GC,而且Eden区的容量小。

  • Mark-compact算法

   即标记整理算法,与标记清除算法不同,标记整理算法避免了内存碎片问题,它将所有存活的对象向内存的一端移动,“整理”完成后,一端是存活的对象一端是可回收内存,然后直接清除可回收内存。

1.3 GC收集器

  • Serial收集器

   最基本、最古老的收集器。这是一个单线程收集器,GC过程中,应用会被停掉,即stop-the-world。

  • Parnew收集器

   实现代码与serial差不多,不同的是这是一个多线程回收器。

  • Paralled scavenge收集器

     Paralled scavenger收集器是一个新生代回收器,使用复制算法,也是一个多线程并行收集器。parallel scavenge收集器专注于提高吞吐量,吞吐量定义为:

            吞吐量 = 用户程序执行时间/(用户程序执行时间 + 垃圾回收时间)

  • Serial old收集器

   Serial old是Serial收集器的老年代版本。

  • Parallel old收集器

   Parallel Scavenge收集器的老年代版本。使用标记-整理算法。

  • CMS(concurrent mark sweep)收集器:并发标记清除收集器,以最短停顿时间为目标的收集器。采用标记—清除算法实现。

2.VisualVM1实际监控JVM状态

2.1 常用调优参数列表

  主要需要熟悉的是总存储空间大小,各个区的比例设置,针对不同的区设定不同的回收器和回收算法。在默认情况下有些选项是不打开的,因此需要手动配置,并且根据自己应用的情况选择适当的参数。

参数 描述

–XX:+UseSerialGC

使用串行GC收集器

–XX:+UseParallelGC

 使用并行GC收集器

–XX:+UseParallelOldGC

使用parallel old收集器 

–XX:+UseConcMarkSweepGC
使用CMS收集器 
 -Xms  初始状态堆大小
 -Xmx 堆的最大大小
 -XX:MaxPermSize=n  设置Permanent区的大小
 -XX:NewSize=n  设置Young generation大小
-XX:NewRatio=n  设置年轻代和年老代的比值

 2.2 查看并分析GC日志

    对于应用程序,在eclipse中可以通过工程属性增加VM属性,将GC输出保存为日志文件。

  

  GC输出选项:

  -XX:+PrintGC 输出GC日志-XX:+PrintGCDetails 输出GC的详细日志-XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)-XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)-XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息-Xloggc:../logs/gc.log 日志文件的输出路径

  日志输出形式:

Java HotSpot(TM) Client VM (25.45-b02) for windows-x86 JRE (1.8.0_45-b14), built on Apr 10 2015 10:46:40 by "java_re" with MS VC++ 10.0 (VS2010)
Memory: 4k page, physical 2074576k(402044k free), swap 4149152k(1441572k free)
CommandLine flags: -XX:InitialHeapSize=16777216 -XX:MaxHeapSize=268435456 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:-UseLargePagesIndividualAllocation
Heapdef new generation   total 4928K, used 885K [0x04600000, 0x04b50000, 0x09b50000)eden space 4416K,  20% used [0x04600000, 0x046dd5f0, 0x04a50000)from space 512K,   0% used [0x04a50000, 0x04a50000, 0x04ad0000)to   space 512K,   0% used [0x04ad0000, 0x04ad0000, 0x04b50000)tenured generation   total 10944K, used 0K [0x09b50000, 0x0a600000, 0x14600000)the space 10944K,   0% used [0x09b50000, 0x09b50000, 0x09b50200, 0x0a600000)Metaspace       used 98K, capacity 2242K, committed 2368K, reserved 4480K

  编写了一个简单的递归计算Fibbonaccy数列的程序,并在最后增加了一句System.gc()强制进行Full GC,得到的GC日志如下,回收后Eden区使用量为0。当服务器型的应用运行起来时,免不了会有多次GC,通过GC日志可以比较容易定位性能问题,比如full gc次数过多等。

{Heap before GC invocations=0 (full 0):def new generation   total 4928K, used 1522K [0x04600000, 0x04b50000, 0x09b50000)eden space 4416K,  34% used [0x04600000, 0x0477c9e8, 0x04a50000)from space 512K,   0% used [0x04a50000, 0x04a50000, 0x04ad0000)to   space 512K,   0% used [0x04ad0000, 0x04ad0000, 0x04b50000)tenured generation   total 10944K, used 0K [0x09b50000, 0x0a600000, 0x14600000)the space 10944K,   0% used [0x09b50000, 0x09b50000, 0x09b50200, 0x0a600000)Metaspace       used 259K, capacity 2280K, committed 2368K, reserved 4480K
15.463: [Full GC (System.gc()) 15.477: [Tenured: 0K->776K(10944K), 0.0428098 secs] 1522K->776K(15872K), [Metaspace: 259K->259K(4480K)], 0.0688257 secs] [Times: user=0.02 sys=0.00, real=0.07 secs]
Heap after GC invocations=1 (full 1):def new generation   total 4992K, used 0K [0x04600000, 0x04b60000, 0x09b50000)eden space 4480K,   0% used [0x04600000, 0x04600000, 0x04a60000)from space 512K,   0% used [0x04a60000, 0x04a60000, 0x04ae0000)to   space 512K,   0% used [0x04ae0000, 0x04ae0000, 0x04b60000)tenured generation   total 10944K, used 776K [0x09b50000, 0x0a600000, 0x14600000)the space 10944K,   7% used [0x09b50000, 0x09c122f0, 0x09c12400, 0x0a600000)Metaspace       used 259K, capacity 2280K, committed 2368K, reserved 4480K
}
Heapdef new generation   total 4992K, used 45K [0x04600000, 0x04b60000, 0x09b50000)eden space 4480K,   1% used [0x04600000, 0x0460b4a8, 0x04a60000)from space 512K,   0% used [0x04a60000, 0x04a60000, 0x04ae0000)to   space 512K,   0% used [0x04ae0000, 0x04ae0000, 0x04b60000)tenured generation   total 10944K, used 776K [0x09b50000, 0x0a600000, 0x14600000)the space 10944K,   7% used [0x09b50000, 0x09c122f0, 0x09c12400, 0x0a600000)Metaspace       used 259K, capacity 2280K, committed 2368K, reserved 4480K

测试环境:

  JVM: Java HotSpot(TM) Client VM (25.60-b23, mixed mode, sharing)
  Java: version 1.8.0_60, vendor Oracle Corporation

Step1:

  监控界面,能够直观地看到JVM各个区域的内存使用情况。除了监视虚拟机,还可以监视应用的内存使用情况。尝试对Eclipse的启动进行优化,可以很明显的看到eclipse启动时,S0的对象向S1拷贝,而old区的使用量略微增加。

  

  还可以监控当前CPU和内存负载情况,类加载数量和线程数:

  

  

Step2:

  eclipse安装目录下有个.ini文件,即eclipse的配置文件,将需要的参数配置填写进去即可。启动eclipse后,查看GC日志,发现整个启动过程中共发生了27次GC,其中有3次Full GC,整个启动过程,我掐指一算大概6~7秒,相当慢了。

  通过参数-XX:NewSize=n 将Eden区重设为128m后,再次启动eclipse发现,这次就只发生了11次GC,下降了一般还多,启动速度也明显比原来快了一些。

Step3:  

  接着使用-Xverify:none禁掉类加载时的字节码验证过程,GC次数为10次,现在启动速度基本为3秒多左右,比原来快了一倍。

{Heap before GC invocations=10 (full 4):def new generation   total 36864K, used 35041K [0x04400000, 0x06bf0000, 0x0eea0000)eden space 32832K, 100% used [0x04400000, 0x06410000, 0x06410000)from space 4032K,  54% used [0x06410000, 0x06638570, 0x06800000)to   space 4032K,   0% used [0x06800000, 0x06800000, 0x06bf0000)tenured generation   total 57224K, used 40267K [0x0eea0000, 0x12682000, 0x24400000)the space 57224K,  70% used [0x0eea0000, 0x115f2ca0, 0x115f2e00, 0x12682000)Metaspace       used 31836K, capacity 33329K, committed 33408K, reserved 34176K
5.742: [GC (Allocation Failure) 5.742: [DefNew: 35041K->4031K(36864K), 0.0193873 secs] 75308K->46613K(94088K), 0.0194649 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 

  然而这种调优粒度太粗,服务器上程序需要定位更精确的时间,所以需要更多参数来调试。

  先写到这里吧。  

  玄不救非,氪不改命。

Reference

  1.http://timyang.net/java/java_gc_tunning/

  2.ImportNew

一次JVM调优的笔记相关推荐

  1. jvm相关,垃圾收集算法,垃圾收集器,jvm调优--学习笔记

    对内存合理分配,优化jvm 参数,就是为了尽可能减少新生代(Minor GC),或者是整个老年代(Major GC) ,或者是整个 Java 堆 (Full GC) ,尽量减少 GC 带来的系统停顿, ...

  2. JVM调优学习笔记整理

    1.相关基础知识 1.1 JVM内存模型 参见blog:https://blog.csdn.net/lydon1314/article/details/120716778 网址:https://zhu ...

  3. 一次 JVM 调优的笔记

    2019独角兽企业重金招聘Python工程师标准>>> 1. JVM Tuning基础知识 1.1 Java堆结构 Java堆可以处于物理上不连续的内存空间上,只要逻辑上是连续的即可 ...

  4. 后端技术:Spring Boot 项目优化和 JVM 调优,真实有效。

    项目调优 作为一名工程师,项目调优这事,是必须得熟练掌握的事情. 在SpringBoot项目中,调优主要通过配置文件和配置JVM的参数的方式进行. 一.修改配置文件 关于修改配置文件applicati ...

  5. JVM调优之 -Xms -Xmx -Xmn -Xss

    原博客地址:http://uule.iteye.com/ 1.JVM垃圾回收与性能调优总结 2.JVM调优的几种策略 一.JVM内存模型及垃圾收集算法  1.根据Java虚拟机规范,JVM将内存划分为 ...

  6. JVM调优-配置参数

    什么时候需要调优 非计算密集型任务cpu占用过高 老年代已使用空间大于70% Full GC频繁 单次GC时间大于1秒 出现OOM 程序的响应速度明显变慢 示例情况 非计算密集型任务cpu占用过高:有 ...

  7. 纯手写2022年最新JVM调优实战手册,看完让你精通JVM调优

    很多程序员不重视 JVM 内存调优,写出来的代码经常出现 OOM 等内存问题.而且,面试求职者中,很多求职者一旦遇到JVM 或者 JVM 调优方面的问题,往往不知如何回答,才能充分展现自己的能力. j ...

  8. JVM 调优系列 1:“精通 JVM 调优,有过 JVM 调优经验”,简历敢写吗?薪资涨 5k 的技巧!

    文章目录 前言 一.部分大厂对于 JVM GC 的面试题 1.1.百度 1.2.顺丰 1.3.京东 1.4.淘宝 1.5.阿里.蘑菇街 二.Garbage Collectors(GC)作何使用 三.G ...

  9. JVM调优参数: XSS,XMS,XMX

    Xss: 每个线程的栈内存大小; 过大影响程序并发线程数; Xms: 程序初始堆内存大小(存储对象); Xmx: 程序堆内存扩容的最大值; (当堆内存被占满了,会自动扩容,当扩容到xmx设置的值后,报 ...

最新文章

  1. springboot工程添加404页面
  2. Acwing 第 2场热身赛 【完结】
  3. 牛客网(剑指offer) 第六题 旋转数组的最小数字
  4. python计算汉明距离_有效地使用python计算汉明距离
  5. 单片机传输浮点数给android,请问单片机怎么接收从串口发送过来的浮点数?
  6. POJ-2533 Longest Ordered Subsequence
  7. 如何让程序一直运行_VBA程序正式运行前,要该如何进行调试呢?
  8. GB28181系统设计(四)-横向扩展和纵向扩展
  9. 工作中 linux 常用命令:vi、cp、mv、rm、kill、curl、tail
  10. xshell远程控制(连接)两个VMware同时启动的Linux操作系统
  11. leetcode problem 41 -- First Missing Positive
  12. 游戏挂机时计算机设置在哪里,蜂窝助手怎么挂机 游戏蜂窝电脑版挂机设置教程...
  13. python应对反爬虫策略_python解决网站的反爬虫策略总结
  14. 美图嗅嗅+到意大利的水族馆里吃西餐
  15. 使用pandas对excel表格筛选
  16. D-Link DCS系列监控账号密码信息泄露
  17. 跟叶子学把妹——教程序猿把妹第三集
  18. 不要再这样做shopee虾皮跨境电商,不然有苦说不出
  19. 开源的抖音壁纸即刻取图出现“这张图不见了,联系客服解决吧”的解决办法
  20. JavaScript:moment12小时制和24小时制

热门文章

  1. 中间件-MyCat学习笔记
  2. vasp算表面吸附流程_VASP表面吸附计算实例分析
  3. 速算C语言程序设计,C语言速算24数据结构课程设计最终版(备份存档)
  4. 微信小程序实现历史搜索功能(h5同理)
  5. Navigation的基本使用
  6. 有关日期参数匹配数据库数据的方法
  7. Windows11-Redis 最新安装教程
  8. 最新最安全代理服务搭建(Websocket-Web-TLS)
  9. vue 能拿到对象 打印对象 但获取不到具体属性 属性 undefined
  10. win7计算机总是卡住,win7系统电脑画面定格死机的解决方法