JVM调优篇

点赞再看,养成习惯,微信搜索「 小大白日志」关注这个搬砖人。

文章不定期同步公众号,还有各种一线大厂面试原题、我的学习系列笔记。

基础概念

  • 一般JVM调优,重点在于调整JVM堆大小、调整垃圾回收器
  • jvm调优的目的是,减少full gc、降低gc停顿时间、提高吞吐量;调优的顺序=”提高吞吐量”>”降低gc停顿时间”;在满足吞吐量的前提下,再降低gc停顿时间;若不能同时满足以上,则选择最适合系统的一种调优结果

JVM调优常用参数

  • -Xmx1024m:最大堆内存,当物理内存不超过192m时最大堆内存为物理内存的一半,否则为物理内存的四分一
  • -Xms1024m:最小堆内存,一般设置为与-Xmx同等值
  • -XX:+PrintGCDetails:输出gc详细日志
  • -XX:+PrintGCTimeStamps或-XX:+PrintGCDateStamps:输出gc信息时带上时间戳
  • jcmd:专用于查看JVM状态,可以查看正在运行的进程,会显示出进程号
    JVM调优篇
  • jmap -heap 10864:查看进程号为10864的进程的堆使用情况

具体参数如下:

F:\Iwebapp\demo-test>jmap -heap 10864
Attaching to process ID 10864, please wait...

Debugger attached successfully.

Server compiler detected.

JVM version is 25.65-b01

using thread-local object allocation.

Parallel GC with 4 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0   //&#x7A7A;&#x4F59;&#x5806;&#x5185;&#x5B58;&#x6700;&#x5C0F;&#x767E;&#x5206;&#x6BD4;&#xFF0C;HeapFreeRatio=&#x7A7A;&#x95F2;&#x5806;&#x5185;&#x5B58;&#x7684;&#x767E;&#x5206;&#x6BD4;=&#x73B0;&#x6709;&#x7A7A;&#x95F2;&#x5806;&#x5185;&#x5B58;/&#x603B;&#x5171;&#x5BF9;&#x5185;&#x5B58;*100,&#x5F53;MinHeapFreeRatio<heapfreeratio时,在每次垃圾回收之后需要进行对扩容 maxheapfreeratio="100" 空余堆内存最大百分比 maxheapsize="1044381696" (996.0mb) 996.0mb="&#x6700;&#x5927;&#x5806;&#x5185;&#x5B58;&#x65E0;&#x7269;&#x7406;&#x5185;&#x5B58;1/4=4G*1/4&#x7EA6;&#x7B49;&#x4E8E;1G" newsize="22020096" (21.0mb) 年轻代堆内存的初始大小 maxnewsize="348127232" (332.0mb) 年轻代堆内存的允许最大值,因为年轻代:老年代="1:2,&#x6240;&#x4EE5;&#x5E74;&#x8F7B;&#x4EE3;&#x6700;&#x5927;=996*1/3=332" oldsize="45088768" (43.0mb) newratio="2" 老年代:年轻代="2&#xFF1A;1" survivorratio="8" 年轻代中eden区:survivor区="8&#xFF1A;2&#xFF0C;Survivor&#x533A;=SurvivorFrom&#x533A;+SurvivorTo&#x533A;=1+1=2" metaspacesize="21807104" (20.796875mb) jdk1.8之后使用的元空间默认大小 compressedclassspacesize="1073741824" (1024.0mb) maxmetaspacesize="17592186044415" mb jdk1.8之后使用的元空间的最大值 g1heapregionsize="0" (0.0mb) 若使用g1垃圾回收器,jvm把堆内存每个多个大小相等的区域,指定每个区域的大小 heap usage: ps young generation eden space: 年轻代的使用情况 capacity="289931264" (276.5mb) used="160612016" (153.1715545654297mb) free="129319248" (123.32844543457031mb) 55.39658392963099% from survivorfrom区的使用情况 (5.5mb) (0.0625mb) (5.4375mb) 1.1363636363636365% to survivorto区的使用情况 (5.0mb) 0.0% old 老年代的使用情况 (36.0mb) (13.065399169921875mb) (22.934600830078125mb) 36.29277547200521% < code></heapfreeratio时,在每次垃圾回收之后需要进行对扩容>

监控JVM

实战源码:以demo-test工程为例,用gcviewner和jdk内置的监控jvm命令来做jvm调优

package com.example.demo;
import com.example.util.ThreadTest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoTestApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoTestApplication.class, args);
        ThreadTest.testJVM();
    }

}

public class ThreadTest {

    public static void main(String[] args) {
        testJVM();
    }

    public static void testJVM(){
        //&#x533F;&#x540D;&#x5185;&#x90E8;&#x7C7B;&#x91CD;&#x5199;Runnable&#x7684;run&#x65B9;&#x6CD5;&#x53EF;&#x4EE5;&#x5199;&#x6210;&#x7BAD;&#x5934;&#x51FD;&#x6570;&#xFF1A;()->{run&#x65B9;&#x6CD5;&#x7684;&#x5185;&#x5BB9;}
        //1000ms&#x540E;&#x6BCF;50ms&#x6267;&#x884C;&#x521B;&#x5EFA;1&#x4E2A;&#x7EBF;&#x7A0B;&#xFF0C;&#x6BCF;&#x4E2A;&#x7EBF;&#x7A0B;150*512*1024byte=150*512*1024B=150*512k=150*0.5M=75M&#xFF0C;1s&#x5185;&#x6700;&#x591A;1000/50=20&#x4E2A;&#x7EBF;&#x7A0B;&#xFF0C;&#x5219;1s&#x5185;&#x6700;&#x5927;&#x5360;&#x7528;&#x5185;&#x5B58;=75*20=150M
        Executors.newScheduledThreadPool(1).scheduleAtFixedRate(()->{
            new Thread(()->{
                for(int i=1;i<=150;i++){ byte[] b="new" byte[1024*512]; 0.5m } system.out.println(thread.currentthread().getname()+"已分配512k内存..."); }).start(); },1000,50,timeunit.milliseconds); < code></=150;i++){>

在target目录下【java -jar -Xloggc:gc.log -Xmx35m -Xms35m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps demo-test.jar】启动jar包或者直接在idea中添加【-Xloggc:gc.log -Xmx35m -Xms35m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps】启动springboot启动类,以下用gcviewner监控JVM :

  • gcviwner

gcviwner是一款可以监控GC日志的工具,前提是要拿到gc日志,gcviwner用法可参考【https://github.com/chewiebug/GCViewer】 ,命令 【java -jar gcviewer-1.37-SNAPSHOT.jar】启动gcviwner,并导入gc.log日志,如下,

JVM调优篇

JVM调优篇

JVM调优篇

上中下三张图,由上图可知吞吐量为74.26%,一般可以达到90%以上,红线是堆的实时总内存,蓝线是堆的实时已使用内存,灰色为young gc,黑色为full gc,可知灰色的线太密集=young gc频繁,黑色的线也是太密集=full gc频繁;full gc总数为296,一般可以把full gc降到个位数;

由中图可知最大停顿时间比较大,达到了892ms,一般可调优到几十毫秒级别;

有下图可看到young gc和full gc的情况,full gc次数296,比较频繁;同时元空间metadata区域过小,可以适当调大

由上,把metadata调为64M,执行【java -jar -XX:MetaspaceSize=64m -Xloggc:gc.log -Xmx35m -Xms35m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps demo-test.jar】重新启动jar包:

JVM调优篇

JVM调优篇

可知full gc次数还是比较多、最大停顿时间也比较长、吞吐量也低,尝试着增大’最大堆内存’,执行【java -jar -XX:MetaspaceSize=64m -Xloggc:gc.log -Xmx100m -Xms100m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps demo-test.jar】重新启动jar包:

JVM调优篇

JVM调优篇

可知full gc次数变少了(黑线少了,0次)、最大停顿时间也短了(94.65ms,到了十几毫秒级别)、吞吐量也高了(93.83%)

至此,调优基本满足上面的【减少full gc、降低gc停顿时间、提高吞吐量】的要求。

下面是jdk内置的jvm监控命令

  • jstat命令

jstat命令用于监视虚拟机的运行状态,命令格式【jstat -参数命令 进程号 间隔毫秒数 总输出次数】,主要参数项:

JVM调优篇
//&#x6BCF;1000ms&#x7EDF;&#x8BA1;&#x4E00;&#x6B21;demo-test-0.0.1.jar&#x7684;gc&#x4FE1;&#x606F;
jstat -gc $(jcmd | grep "demo-test-0.0.1.jar" | awk '{print $1}') 1000

JVM调优篇
S0C、S1C、S0U、S1U:C是总量,U是使用量,代表S0(survivorFrom区)和S1(survivorTo区)的总量与使用量

EC、EU:Eden区总量与使用量

OC、OU:Old区总量与使用量

MC、MU: Metaspace区(元空间)总量与使用量

YGC、YGCT:young gc的次数与时间

FGC、FGCT:full gc的次数与时间<

GCT:总的GC时间

//&#x6BCF;1000ms&#x7EDF;&#x8BA1;&#x4E00;&#x6B21;&#x8FDB;&#x7A0B;ID&#x4E3A;10492&#x7684;gc&#x4FE1;&#x606F;&#xFF0C;&#x5171;&#x7EDF;&#x8BA1;10&#x6B21;&#x6570;&#x7ED3;&#x675F;&#x7EDF;&#x8BA1;
jstat -gc 10492 10

JVM调优篇
  • jps

jps可以查看正在运行的java进程,命令格式【jsp 参数】,主要参数项:

JVM调优篇
&#x3010;jsp -l&#x3011;&#x67E5;&#x770B;&#x5177;&#x4F53;&#x7684;&#x5305;&#x540D;

JVM调优篇
  • jinfo

可以查看启动jar包时未显式指定的系统默认值,以及动态修改这些默认值,命令格式【jinfo -flag 默认的参数 进程id】,查看【年轻代:老年代】的内存比例:

JVM调优篇
  • jmap

jmap查看java内存信息,命令格式【jmap -参数 进程id】,参数项:

JVM调优篇
&#x5B9E;&#x4F8B;&#x5982;&#x4E0A;&#xFF1A;&#x3010;jmap -heap 10864&#x3011;&#x67E5;&#x770B;&#x8FDB;&#x7A0B;&#x53F7;&#x4E3A;10864&#x7684;&#x8FDB;&#x7A0B;&#x7684;&#x5806;&#x4F7F;&#x7528;&#x60C5;&#x51B5;
  • jstack

jstack是一个非常有用的命令,可以查看正在运行的线程的堆栈信息,比如查看后天没有相应的线程在做些什么,在等待什么资源,命令格式【jstack 参数项 进程号】,主要参数项如下:

JVM调优篇
//&#x67E5;&#x770B;&#x8FDB;&#x7A0B;&#x7684;&#x5806;&#x6808;&#x53CA;&#x9501;&#x7684;&#x4FE1;&#x606F;
jstack -l 10220

JVM调优篇
图中线程状态是很重要的一个要素:
JVM调优篇

CMS收集器和G1收集器的调优

启动各种垃圾收集器

参数 说明 -XX:+UseParallelGC 新生代使用并行回收收集器 -XX:+Use ParalleloldGC 老年代使用并行回收收集器 -XX:ParallelGCThreads 设置用于垃圾回收的线程数 -XX:+UseAdaptiveSizePolicy 打开自适应GC策略

CMS和G1的调优
  • cms是分代收集算法中老年代的算法(用标记整理算法),G1却适用于年轻代和老年代,故G1可以采用复制算法不会导致内存碎片,而cms不能采用年轻代的复制算法而导致有内存碎片
  • G1是由一个个区域块组成的,即使有碎片也只会影响某个区域块,不会影响整个堆
  • cms采用老年代标记整理算法,需要扫描整个表来标记整理,故存在停顿(即使它是并发);G1的停顿取决于需要收集的’区域块’个数,而不用等整个堆空间,所以g1的停顿时间比cms少

OK,如果文章哪里有错误或不足,欢迎各位留言。

创作不易,各位的「 三连」是二少创作的最大动力!我们下期见!

Original: https://www.cnblogs.com/mofes/p/15068642.html
Author: 明天喝可乐
Title: JVM调优篇

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/589755/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • ||运算你真的了解吗?

    或运算介绍 或运算:只要有一个条件为true,即为true。 通过如上逻辑关系图,还有另外一层 隐含的意思: 如果A条件是true,B条件不执行! 如果A条件是false,B条件要…

    Java 2023年6月8日
    063
  • Docker 学习笔记一

    Docker 学习笔记一 1.Docker是什么? Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。让开发者打包他们的应用以及依赖包…

    Java 2023年6月16日
    0111
  • [spring]spring静态代理和aop

    10.代理模式 代理模式的分类: 静态代理 动态代理 关系分析 抽象角色:一般会使用接口或者抽象类 真实角色:被代理的角色 代理角色:代理真实的角色,做一些附属的操作 客户:访问代…

    Java 2023年6月6日
    071
  • Redis分布式锁实现

    Redis分布式锁实现 在分布式环境下,利用Redis实现锁机制,避免资源竞争的做法非常常见。这里探讨一下Redis分布式锁的实现方式、可能存在的问题以及适用场景。 setnx 最…

    Java 2023年6月13日
    088
  • org.springframework.web.method.HandlerMethod 与 org.springframework.messaging.handler.HandlerMethod 转换失败

    Springmvc hander.getclassclass org.springframework.web.method.HandlerMethod HandlerMethod….

    Java 2023年5月30日
    054
  • 聊聊消息队列高性能的秘密——零拷贝技术

    前言 RocketMQ为什么这么快、Kafka为什么这么快?用了零拷贝技术?什么是零拷贝技术,它们二者的零拷贝技术有不同吗? 为什么需要零拷贝 在计算机产业中,I/O的速度相较CP…

    Java 2023年6月6日
    0107
  • 25. Apache Shiro Java反序列化漏洞

    前言: 最近在审核漏洞的时候,发现尽管Apache shiro这个反序列化漏洞爆出来好久了,但是由于漏洞特征不明显,并且shiro这个组件之前很少听说,导致大厂很多服务还存在shi…

    Java 2023年5月29日
    094
  • Liunx(CentOS)安装Nacos(单机启动,绑定Mysql)

    Liunx安装Nacos(单机启动,绑定Mysql) 一,准备安装包 github下载点 二,在/usr/local/目录下创建一个文件夹用于上传和解压Nacos cd /usr/…

    Java 2023年6月15日
    073
  • 【设计模式】Java设计模式-适配器模式

    【设计模式】Java设计模式 – 适配器模式 😄 不断学习才是王道🔥 继续踏上学习之路,学之分享笔记👊 总有一天我也能像各位大佬一样🏆原创作品,更多关注我CSDN: 一…

    Java 2023年6月16日
    075
  • linux 安装vsftpd

    一,安装vsftpd 1.安装: [root@localhost pluto]# yum -y install vsftpd 安装完后,有/etc/vsftpd/vsftpd.co…

    Java 2023年6月9日
    090
  • 利用docker部署oxidized网络设备备份系统

    随着网络设备的增多,通过人手备份网络设备倍感压力,而且效率低。有编程基础的人可能会通过Python的parimiko 或者netmiko 连接到设备操作 把文件通过ftp 上传到F…

    Java 2023年6月8日
    0167
  • GitLab 服务搭建

    GitLab 概述 GitLab 是一个用于仓库管理系统的开源项目,使用 Git 作为代码管理工具,并在此基础上搭建起来的 web 服务。GitLab 产品将分为三个发行版本 CE…

    Java 2023年6月7日
    063
  • JavaScript基本语法

    JavaScript(js)注释 js的注释非常简单,就和java一样, //, /**/,分别对应多行注释和单行注释,当然要在 <script>….</sc…

    Java 2023年6月5日
    087
  • Java的线程状态

    在我们平时写code的时候,经常会使用到多线程。其中线程所处的状态就是我们需要进程思考的问题。 线程有哪些状态 NEW: 一个线程刚被创建,但是没有被使用就是处于这个状态RUNNA…

    Java 2023年6月7日
    090
  • Java学习 (20) Java数组篇(04)Arrays类&冒泡排序&稀疏数组

    Arrays类 语法实例 冒泡排序 语法实例 具体讲解视频(狂神说Java) 稀疏数组 语法实例 具体讲解视频(狂神说Java) Arrays类 教组的工具类java.util.A…

    Java 2023年6月8日
    0104
  • DeferredResult异步处理spring mvc Demo

    spring mvc同步接口在请求处理过程中一直处于阻塞状态,而异步接口可以启用后台线程去处理耗时任务。简单来说适用场景:1.高并发;2.高IO耗时操作。 Spring MVC3….

    Java 2023年5月29日
    065
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球