一步一步带你理解Java8 JVM调优_峡谷程序猿的博客-程序员宝宝_jvm8调优参数

技术标签: jvm  Java  java  

做了五年Java开发,一直有了解jvm的调优知识点,但在实际项目中确很少去对jvm进行调优,今天就下个决心,好好研究一下jvm调优相关的知识点。现在最常用的还是Java8 , 那就以Java8为例来做调优实践。

以下是Java虚拟器启动时内存条的大致结构图:
在这里插入图片描述
在对jvm进行优化时,最主要的就是对堆内存和Java虚拟机栈的大小进行优化。

首先还是看一下oracle官方给的调优说明文档:
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/sizing.html#defaults_survivor_space

  • Java虚拟机栈调优配置
    Java虚拟机栈是描述java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。栈帧( Frame)是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接(Dynamic Linking)、 方法返回值和异常分派( Dispatch Exception)。栈帧随着方法调用而创建。随着方法结束而销毁——无论方法是正常完成还是异常完成(抛出了在方法内未被捕获的异常)都算作方法结束。
    设置Java虚拟机栈的核心配置是:-Xss 。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K.更具应用的线程所需内存大小进行 调整.在相同物理内存下,减小这个值能生成更多的线程。
    Java虚拟机栈的大小直接影响到方法的调用深度,比如递归调用。因此需要根据自身的应用场景来设置这个值,这个很关键!。这里我设置为512k 。对应配置为: -Xss512k

  • Heap堆内存调优

以下为堆内存结构图:
堆内存结构图
这里设计到两个大区域:

  1. young generation 新生代
    是用来存放新生的对象。一般占据堆的1/3空间。由于频繁创建对象,所以新生代会频繁触发MinorGC 进行垃圾回收。新生代又分为 Eden 区、ServivorFrom、ServivorTo 三个区。

  2. Tenured Generation 老年代
    主要存放应用程序中生命周期长的内存对象。
    老年代的对象比较稳定,所以 MajorGC 不会频繁执行。在进行 MajorGC 前一般都先进行了一次 MinorGC,使得有新生代的对象晋身入老年代,导致空间不够用时才触发。当无法找到足够大的连续空间分配给新创建的较大对象时也会提前触发一次 MajorGC 进行垃圾回收腾出空间。MajorGC 采用标记清除算法:首先扫描一次所有老年代,标记出存活的对象,然后回收没有标记的对象。MajorGC 的耗时比较长,因为要扫描再回收。MajorGC 会产生内存碎片,为了减少内存损耗,我们一般需要进行合并或者标记出来方便下次直接分配。当老年代也满了装不下的时候,就会抛出 OOM(Out of Memory)异常。

当OOM异常可以使用dump来记录异常的详细信息。jvm配置参数为:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/app/log/dump

  1. 元数据空间
    元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。类的元数据放入 nativememory, 字符串池和类的静态变量放入 Java 堆中,这样可以加载多少类的元数据就不再由MaxPermSize 控制, 而由系统的实际可用空间来控制。

Heap的大小涉及到四个主要配置参数:

参数 说明 默认值
MinHeapFreeRatio GC后Heap空闲的最小比例 40
MaxHeapFreeRatio GC后Heap空闲的最大比例 70
-Xms Heap的初始化大小 6656k
-Xmx Heap的最大大小 calculated

官方给出的建议:
The following are general guidelines regarding heap sizes for server applications:
Unless you have problems with pauses, try granting as much memory as possible to the virtual machine. The default size is often too small.
Setting -Xms and -Xmx to the same value increases predictability by removing the most important sizing decision from the virtual machine. However, the virtual machine is then unable to compensate if you make a poor choice.
In general, increase the memory as you increase the number of processors, since allocation can be parallelized.

意思是建议将Heap的初始值和最大值设置为相同。

The default maximum heap size is half of the physical memory up to a physical memory size of 192 megabytes (MB) and otherwise one fourth of the physical memory up to a physical memory size of 1 gigabyte (GB).
这意思是当物理内存小于1G时,默认的最大Heap的大小为物理内存的一半。当物理内存大于1G时,默认的堆最大值为物理内存的四分之一。

也就是说,当我们服务器的内存为4G时,推荐使用如下配置:

-Xms1024m -Xmx1024m

当确定了Heap的取值,现在就要考虑到Young Generation 和 Tenured Generation比例的分配啦。

参数 说明 默认值
NewRatio the ratio between the young and tenured generation.新生代与老年代的比例 2
NewSize the young generation size . 新生代的大小 1310M
MaxNewSize the young generation max size.新生代最大值 not limited
SurvivorRatio the ratio between eden and a survivor space. eden区与survivor区的比例 8
  • NewRatio
    从结构关系中可以看到: heap = young + tenured
    当Heap的大小确定后,可以通过NewRatio来调整young和tenured的大小。
    NewRatio = tenured / young ; 默认值为2
    得出: young = 1/3 heap ; tenured = 2/3 heap

因此当Heap大小确定之后,直接指定NewRatio的值就可以确定新生代young和老年代tenured的大小了,因此得出如下jvm配置:

-XX:NewRatio=3

  • NewSize 和 MaxNewSize

理论上,如果指定了NewRatio就不需要再去配置NewSize了。因为NewSize的值基本上确定了。以Heap=1G为例,NewSize=1/3G

The parameters NewSize and MaxNewSize bound the young generation size from below and above. Setting these to the same value fixes the young generation, just as setting -Xms and -Xmx to the same value fixes the total heap size. This is useful for tuning the young generation at a finer granularity than the integral multiples allowed by NewRatio.

官方说明:建议将NewSize 和 MaxNewSize设置相同。这两个参数配置比使用NewRatio控制的颗粒度更精细。也就是说建议使用这两个参数来指定young generation所占内存空间大小。

因此得出jvm设置:
-XX:NewSize=360M -XX:MaxNewSize=360M

  • SurvivorRatio
    eden区与survivor区的比例 ,由于Survivor区包含 from survivor 和 to survivor 。from和to的大小是相同的。
    举个例子:
    SurvivorRatio默认值是8
    意思是: survivor = 1/8 eden = from + to ;
    from = 1/10 young ;
    to = 1/10 young ;
    eden = 8/10 young ;

因此得出jvm配置:

-XX:SurvivorRatio=8

对于堆内存的分配会直接影响Java的垃圾回收机制。因此jvm调优的核心逻辑还是控制其垃圾回收的方式。

打印jvm垃圾回收日志命令如下:

-XX:+PrintGCDetails
-Xloggc:/var/app/loggs/gc.log

  • 垃圾回收器的选择

除非您的应用程序有非常严格的暂停时间要求,否则请先运行您的应用程序并允许VM选择收集器。如有必要,请调整堆大小以提高性能。如果性能仍然不能达到您的目标,请使用以下准则作为选择收集器的起点。

1 如果应用程序的数据集较小(最大约100 MB),则选择带有选项-XX:+ UseSerialGC的串行收集器。

2 如果应用程序将在单个处理器上运行,并且没有暂停时间要求,则让VM选择收集器,或通过选项-XX:+ UseSerialGC选择串行收集器。

3 如果(a)峰值应用程序性能是第一要务,并且(b)没有暂停时间要求或可接受1秒或更长时间的暂停,则让VM选择收集器,或使用-XX:+ UseParallelGC选择并行收集器。

4 如果响应时间比整体吞吐量更重要,并且垃圾收集暂停时间必须保持小于1秒,那么请使用-XX:+UseConcMarkSweepGC或-XX:+ UseG1GC选择并发收集器。

这些准则仅为选择收集器提供了一个起点,因为性能取决于堆的大小,应用程序维护的实时数据量以及可用处理器的数量和速度。暂停时间对这些因素特别敏感,因此前面提到的1秒阈值仅是近似值:在许多数据大小和硬件组合上,并行收集器的暂停时间将超过1秒。相反,在某些组合上,并发收集器可能无法将暂停时间保持在1秒以内

我比较看着响应时间,因此这里选择使用标记清除算法的CMS垃圾回收器,使用配置:-XX:+UseConcMarkSweepGC

-XX:+PrintFlagsFinal 可以打印jvm的详细配置信息
-XX:+PrintTenuringDistribution 可以打印新生代到老年代的阀值和对象的寿命。

5 元数据空间大小的分配

在Java8中,移除了之前的永久代,将类的元数据信息存放在一块非堆的本地内存中,这一块区域被称之为元数据区(Metaspace),不设置的话元数据空间的大小有机器内存的大小来决定。在实际情况最好是设置一个合适的值。

做如下配置:
-XX:MetaspaceSize=128m
-XX:MaxMetaspaceSize=256m

6 直接内存大小的分配
直接内存顾名思义就是机器上的一块内存。也是一块非堆的内存。直接内存并不是虚拟机运行时数据区的一部分,也不是Java 虚拟机规范中定义的内存区域。在JDK1.4 中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O 方式,它可以使用native 函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。

这篇文章对直接内存有详细说明:https://blog.csdn.net/y3over/article/details/88791958

jvm设置参数如下(直接内存默认大小为64m):
-XX:MaxDirectMemorySize=1024m
-XX:+DisableExplicitGC

-XX:+DisableExplicitGC 禁止在代码中显示调用System.gc() 。因为在使用直接内存时会使用DirectByteBuffer对象。它在分配直接内存时会经常调用System.gc(),为了减少gc此时。线上环境建议禁止显示调用System.gc()

综上得到如下配置:
-Xms1024m
-Xmx1024m
-Xss512k
-XX:NewRatio=3
-XX:NewSize=360M
-XX:MaxNewSize=360M
-XX:SurvivorRatio=8
-XX:+PrintGCDetails
-Xloggc:/var/app/loggs/gc.log
-XX:+UseConcMarkSweepGC
-XX:+PrintTenuringDistribution
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/app/log/dump/java_heapdump.hprof
-XX:MetaspaceSize=128m
-XX:MaxMetaspaceSize=256m
-XX:MaxDirectMemorySize=1024m
-XX:+DisableExplicitGC

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zhaodongchao1992/article/details/106566984

智能推荐

夏时制 windows/linux_caolaosanahnu的博客-程序员宝宝

http://zh.wikipedia.org/wiki/%E5%A4%8F%E6%97%B6%E5%88%B6夏时制 维基百科,自由的百科全书跳转到: 导航, 搜索 跳过字词转换说明汉漢▼▲各時區多數位於其理想邊界之西,導致實際上全年實施夏時制。夏时制,又称日光节约时制、日光節約時間(英语:Daylight sa

bzoj1051: [HAOI2006]受欢迎的牛(tarjan板子)_weixin_30667301的博客-程序员宝宝

1051: [HAOI2006]受欢迎的牛Time Limit: 10 SecMemory Limit: 162 MBSubmit: 6064Solved: 3179[Submit][Status][Discuss]Description  每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这种关系是具有传递性的...

查看Linux系统版本信息的命令_weixin_34232617的博客-程序员宝宝

为什么80%的码农都做不了架构师?>>> ...

机器学习-决策树 -计算信息增益_Hello_xzy_Word的博客-程序员宝宝

"""文件说明:决策树"""from math import log"""函数说明:创建测试数据集Parameters: nullReturns: dataSet - 数据集 labels - 分类属性Author: ZhengYuXiaoModify: 2019-03-04"""def createDataSet():

日志分析_low米的博客-程序员宝宝

官方教程地址日志文件日志文件分Dataflash logs 和 tlogs(Telemetry logs)Dataflash :从机载内存卡下载的tlogs:地面站记录的打开Dataflash打开tlogs下面主要看tlog文件机械故障比较真实值和期望值,如果相差太大说明有问题。NAV_CONTROLLER_OUTPUT’s nav_roll (desired roll)...

python利用openpyxl向excel文件追加数据_Newnotes的博客-程序员宝宝

目的:判断EXCEL文件中是否已存在数据,如不存在进行追加。import openpyxlfrom tkinter import messagebox # 弹出提示框filepath = 'paiwuxuke.xlsx'wb = openpyxl.load_workbook(filepath)#获取全部表名sheetnames = wb.sheetnames#切换到目标数据表#ws = wb[]ws = wb['Sheet']#表总行数max_row = ws.max_row#表总

随便推点

GDT与LDT_zmmycsdn的博客-程序员宝宝_gdt和ldt

转载:https://www.cnblogs.com/hicjiajia/archive/2012/05/25/2518684.htmlGDT 与 LDT很长时间没碰组成原理和操作系统,忘得差不多了,今天学内核需要一些基础知识,搜了些文章补习一下,这篇讲描述符表的文章比较不错:原文地址:http://blog.csdn.net/billpig/article/d

Seaborn 库_eagle2728的博客-程序员宝宝

import seaborn as snsimport matplotlib.pyplot as plt%matplotlib inline #是为了在 Jupyter 中正常显示图形,若没有这行代码,图形显示不出来的titanic=sns.load_dataset('titanic') #数据导入sns.barplot(x='class',y='survived',data=tita...

Linux下H.264码流实时RTP打包与发送_学习不止的博客-程序员宝宝

由于项目要求在DM6467T平台上添加实时RTP打包发送模块,这才找了找有没有人分享 这方面的经验。这里需要感谢网友:yanyuan9527,他写的文章对我帮助很大,可以说让一个完全小白的人了解了RTP打包,链接在此:http://www.chinavideo.org/forum.php?mod=viewthread&tid=7575    请大家阅读上面提到的文章,我这里就详细写了,读了之后

WebKit.NET-0.5简单应用_weixin_34409822的博客-程序员宝宝

最近想用c#做个简单的浏览器工具,但是网站一些内容不支持c#内置的WebBowser控件,于是只能改用其他内核浏览器进行开发,搜索到WebKit.NET这个封装好的浏览器引擎,需求的功能也都有,于是用WebKit.NET进行开发。 WebKit.NET官网http://webkitdotnet.sourceforge.net/ WebKit.N...

题解 P3128 【[USACO15DEC]最大流Max Flow】_weixin_30328063的博客-程序员宝宝

简单树剖没什么好讲的,只把几个操作说一下:1、每一次操作都把x到y的点权都加12、最后查一下整个树的点权最大值只需要对【模板】树链剖分 的线段树部分略加修改就OK了,修改就是把累加变成求最大值,简单得不行了。代码:#include<bits/stdc++.h>#define maxn 4000001#define L(x) (x<<1)#define R(...

SSM学习系列(二)Spring对象_weixin_34293246的博客-程序员宝宝

Spring初步使用注入对象沿用上次的工程新建两个类Category和ProductCategory.javapublic class Category { public int getId() { return id; } public void setId(int id) { this.id = ...