JVM GC 调优命令看这一篇就够了

JVM GC 调优命令看这一篇就够了

2023-11-11 23:27·IT果果日记

jstat

可用于统计内存分配速率、GC次数,GC耗时

jstat常用命令格式

jstat -gc <pid> <统计间隔时间> <统计次数>

例如:jstat -gc 6 1000 10 ,统计pid=6的进程,每秒统计1次,统计10次。参数含义:

  • S0C:年轻代中第一个Survivor区的容量,单位为KB。
  • S1C:年轻代中第二个Survivor区的容量,单位为KB。
  • S0U:年轻代中第一个Survivor区已使用大小,单位为KB。
  • S1U:年轻代中第二个Survivor区已使用大小,单位为KB。
  • EC:年轻代中Eden区的容量,单位为KB。
  • EU:年轻代中Eden区已使用大小,单位为KB。
  • OC:老年代的容量,单位为KB。
  • OU:老年代已使用大小,单位为KB。
  • MC:元空间的容量,单位为KB。
  • MU:元空间已使用大小,单位为KB。
  • CCSC:压缩类的容量,单位为KB。
  • CCSU:压缩类已使用大小,单位为KB。
  • YGC:Young GC的次数。
  • YGCT:Young GC所用的时间。
  • FGC:Full GC的次数。
  • FGCT:Full GC的所用的时间。
  • GCT:GC的所用的总时间。

jmap

可用于了解系统运行时的对象分布,查看内存

jmap常用命令格式

# 按照类占用内存大小降序排列,查看对象占用内存情况
 jmap -histo:live <pid>

例如,输入命令 jmap -histo:live 6,如图。参数含义如下:

  • [C is a char[]
  • [S is a short[]
  • [I is a int[]
  • [B is a byte[]
  • [[I is a int[][]

上面的输出中[C对象占用Heap这么多,往往跟String有关,String其内部使用final char[]数组来保存数据的。constMethodKlass/ methodKlass/ constantPoolKlass/ constantPoolCacheKlass/ instanceKlassKlass/ methodDataKlass与Classloader相关,常驻于Perm区。

生成堆内存转储快照

生成堆内存转储快照命令格式如下:

# 生成堆内存转储快照,在当前目录下导出dump.hrpof的二进制文件, 
# 可以用eclipse的MAT图形化工具分析
jmap -dump:live,format=b,file=dump.hprof <pid>

例如,输入命令 jmap -dump:live,format=b,file=dump.hprof 6 ,就会生成一个dump.hprof文件

如何在OutOfMemoryError时,自动生成hprof文件

在JVM启动时,添加如下参数:

  • -XX:+HeapDumpOnOutOfMemoryError:当JVM发生OutOfMemoryError错误时,自动生成hprof文件。
  • -XX:HeapDumpPath=:指定hprof文件的输出路径。
  • -XX:HeapDumpInterval=:指定hprof文件生成的时间间隔。
  • -XX:StartFlightRecording:启用Java飞行记录器(JFR),它可以记录应用程序的性能数据,并生成hprof文件。
  • -XX:FlightRecorderOptions:指定Java飞行记录器的配置选项。

如何打开dump文件?

想要打开dump.hprof文件可以利用jdk自带的工具 jvisualvm

点菜单“文件”,选择“装入”

装入时选择文件类型为“堆 Dump”类型

如何分析dump文件?

选择类,然后对堆内存大小进行排序,双击可以查看具体类型的实例内存占用情况

双击具体的实例可以查看该实例的内容和占用的大小,可以选择全部展示或者把该内容保存为一个txt文件

jstack

jstack是JVM自带的Java堆栈跟踪工具,它用于打印出给定的java进程ID、core file、远程调试服务的Java堆栈信息。

  • jstack命令用于生成虚拟机当前时刻的线程快照。
  • 线程快照是虚拟机中每个线程在执行时的方法堆栈的记录集合。生成线程快照的主要目的是帮助定位导致线程长时间停顿的原因,例如线程间的死锁、死循环、长时间等待外部资源等问题。
  • 当线程出现停顿时,使用jstack可以帮助我们查看各个线程的调用堆栈,了解没有响应的线程在后台正在做什么事情或等待什么资源。
  • 当Java程序崩溃并生成core文件时,jstack工具可以帮助我们获取core文件的java stack和native stack的信息,这样我们就能轻松地了解Java程序崩溃的原因以及问题发生在程序的哪个地方。
  • 另外,jstack工具还可以附属到正在运行的Java程序上,获取当前运行的Java程序的java stack和native stack的信息。如果当前运行的Java程序处于挂起状态,jstack非常有用。

jstack命令格式

jstack命令用于打印指定Java进程、核心文件或远程调试服务器的Java线程的Java堆栈跟踪信息。 jstack命令可以生成JVM当前时刻的线程快照。

jstack [option] pid 
jstack [option] executable core 
jstack [option] [server-id@]remote-hostname-or-IP
  • executable:产生core dump的java可执行程序
  • core: 将被打印信息的core dump文件
  • remote-hostname-or-IP: 远程debug服务的主机名或ip
  • server-id: 唯一id,假如一台主机上多个远程debug服务

线程状态

Java语言定义了6种线程状态:

  • New:创建后尚未启动的线程处于这种状态,不会出现在Dump中。
  • RUNNABLE:包括Running和Ready。线程开启start()方法,会进入该状态,在虚拟机内执行的。
  • Waiting:无限的等待另一个线程的特定操作。
  • Timed Waiting:有时限的等待另一个线程的特定操作。
  • 阻塞(Blocked):在程序等待进入同步区域的时候,线程将进入这种状态,在等待监视器锁。
  • 结束(Terminated):已终止线程的线程状态,线程已经结束执行。

Dump文件的线程状态一般其实就以下3种:

  • RUNNABLE,线程处于执行中
  • BLOCKED,线程被阻塞
  • WAITING,线程正在等待

Monitor 监视锁

每个对象都与一个monitor 相关联。当且仅当拥有所有者时(被拥有),monitor才会被锁定。执行到monitorenter指令的线程,会尝试去获得对应的monitor,如下:

  • 每个对象维护着一个记录着被锁次数的计数器, 对象未被锁定时,该计数器为0。线程进入monitor(执行monitorenter指令)时,会把计数器设置为1.
  • 当同一个线程再次获得该对象的锁的时候,计数器再次自增.
  • 当其他线程想获得该monitor的时候,就会阻塞,直到计数器为0才能成功。

monitor的拥有者线程才能执行 monitorexit指令。线程执行monitorexit指令,就会让monitor的计数器减一。如果计数器为0,表明该线程不再拥有monitor。其他线程就允许尝试去获得该monitor了。

Dump 文件分析关注重点

  • runnable,线程处于执行中
  • deadlock,死锁(重点关注)
  • blocked,线程被阻塞 (重点关注)
  • Parked,停止
  • locked,对象加锁
  • waiting,线程正在等待
  • waiting to lock 等待上锁
  • Object.wait(),对象等待中
  • waiting for monitor entry 等待获取监视器(重点关注)
  • Waiting on condition,等待资源(重点关注),最常见的情况是线程在等待网络的读写

实战一 - jstack 分析死锁问题

什么是死锁?

死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法进行下去。

如何用如何用jstack排查死锁问题?

先来看一段会产生死锁的Java程序,源码如下:

package com.examples.test.thread.deadlock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class DeathLockTest {
    private static Lock lock1 = new ReentrantLock();
    private static Lock lock2 = new ReentrantLock();

    public static void deathLock() {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                try {
                    lock1.lock();
                    System.out.println(Thread.currentThread().getName() + " get the lock1");
                    Thread.sleep(1000);
                    lock2.lock();
                    System.out.println(Thread.currentThread().getName() + " get the lock2");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        Thread t2 = new Thread() {
            @Override
            public void run() {
                try {
                    lock2.lock();
                    System.out.println(Thread.currentThread().getName() + " get the lock2");
                    Thread.sleep(1000);
                    lock1.lock();
                    System.out.println(Thread.currentThread().getName() + " get the lock1");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        //设置线程名字,方便分析堆栈信息
        t1.setName("mythread-果果1号");
        t2.setName("mythread-果果2号");
        t1.start();
        t2.start();
    }

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

运行结果如图:

显然,线程果果1号和线程果果2号都是只执行到一半,就陷入了阻塞等待状态。

jstack排查Java死锁步骤

  • 在终端中输入jsp查看当前运行的java程序
  • 使用 jstack -l pid 查看线程堆栈信息
  • 分析堆栈信息

在终端中输入jsp查看当前运行的java程序

使用 jstack -l pid 查看线程堆栈信息

分析堆栈信息。由上图,可以清晰看到死锁信息:

  • mythread-果果1号 等待这个锁 “0x00000000d5b67c10”,这个锁是由于mythread-果果2号线程持有。
  • mythread-果果2号 等待这个锁 “0x00000000d5b67be0”, 这个锁是由mythread-果果1号线程持有。

实战二 - jstack 分析CPU过高问题

来个导致CPU过高的demo程序,一个死循环

package com.examples.test.thread.jstack;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 有个导致CPU过高程序的demo,死循环
 */
public class JstackCpuCase {
    private static ExecutorService executorService = Executors.newFixedThreadPool(5);

    public static void main(String[] args) {
        Task task1 = new Task();
        Task task2 = new Task();
        executorService.execute(task1);
        executorService.execute(task2);
    }
    public static Object lock = new Object();
    static class Task implements Runnable {
        public void run() {
            synchronized (lock) {
                long sum = 0L;
                while (true) {
                    sum += 1;
                }
            }
        }
    }
}

jstack 分析CPU过高步骤

  • top
  • top -Hp pid
  • jstack pid
  • jstack -l [PID] >/tmp/log.txt
  • 分析堆栈信息

1、top命令。

在服务器上,我们可以通过top命令查看各个进程的cpu使用情况,它默认是按cpu使用率由高到低排序的。

由上图中,我们可以找出pid为21340的java进程,它占用了最高的cpu资源,凶手就是它。

2、top -Hp pid 命令。

通过 top -Hp 21340 可以查看该进程下,各个线程的cpu使用情况,如下:

可以发现pid为21350的线程,CPU资源占用最高,小本本把它记下来,接下来拿jstack给它拍片子

3、jstack pid 命令。

通过top命令定位到cpu占用率较高的线程之后,接着使用jstack pid命令来查看当前java进程的堆栈状态,

jstack 21350后,内容如下:

4、jstack -l [PID] >/tmp/log.txt

其实,前3个步骤,堆栈信息已经出来啦。但是一般在生成环境,我们可以把这些堆栈信息打到一个文件里,再回头仔细分析。

5、分析堆栈信息

我们把占用cpu资源较高的线程pid(本例子是21350),将该pid转成16进制的值。

在thread dump中,每个线程都有一个nid,我们找到对应的nid(5366),发现一直在跑(24行)

这个时候,可以去检查代码是否有问题。 当然,也建议隔段时间再执行一次stack命令,再一份获取thread dump,毕竟两次拍片结果(jstack)对比更准确。

jinfo

用来查看正在运行的 Java 应用程序的扩展参数,包括Java System属性和JVM命令行参数,

命令格式

jinfo [options]

  • jinfo : 打印jvm版本、所有Java System Properties,以及所有VM flags(非常实用)
  • jinfo -flag :打印对应的启动参数的值
  • jinfo -flag [+/-] :启用或禁用对应的启动参数
  • jinfo -flag = :设置对应的启动参数的值

其他GC工具

  • 监控告警系统:Zabbix、Prometheus、Open-Falcon
  • jdk自动实时内存监控工具:VisualVM
  • 堆外内存监控: Java VisualVM安装Buffer Pools 插件、google perf工具、Java NMT(Native Memory Tracking)工具
  • GC日志分析:GCViewer、gceasy
  • GC参数检查和优化:http://xxfox.perfma.com/

GC优化案例

数据分析平台系统频繁Full GC

数据分析平台主要监控用户在APP中的行为并进行定时分析统计,同时支持报表导出功能,采用CMS GC算法进行内存管理。然而,数据分析师在使用过程中发现系统页面打开经常出现卡顿。通过jstat命令的监测,发现每次进行Young GC后,约有10%的存活对象进入到老年代。

造成这一现象的原因是Survivor区的空间设置过小。因此,在每次Young GC后,Survivor区域无法容纳所有的存活对象,导致它们提前进入老年代。为了解决这个问题,我们决定调整Survivor区的大小,使其能够容纳Young GC后的存活对象。

通过调整,我们使得对象在Survivor区经历多次Young GC后,达到一定的年龄阈值,才会被转移到老年代。这样,每次Young GC后进入老年代的存活对象数量大幅减少,仅有几百Kb。这一改变显著降低了Full GC的频率,使系统运行更加稳定。

业务对接网关OOM

系统在运行几小时后出现了OOM(Out Of Memory)错误,并在重启后几小时再次出现。通过分析,在eclipse MAT工具分析中我们发现网关主要消费了Kafka数据,进行数据处理和计算,然后转发到另一个Kafka队列。然而,代码中存在一个问题是异步打印业务Kafka topic数据,由于数据量较大,大量对象在内存中积压等待打印,最终导致了OOM。

账号权限管理系统频繁长时间Full GC

系统提供了各种账号鉴权服务,但在使用过程中,我们发现系统经常无法正常使用。通过Zabbix的监控平台监控发现,系统频繁发生长时间Full GC,但老年代的堆内存并没有占满。经过调查,我们发现业务代码中调用了System.gc()。

https://www.toutiao.com/article/7300222307589866025/?app=news_article&timestamp=1699971838&use_new_style=1&req_id=202311142223582F66879C2A4B511BBBBC&group_id=7300222307589866025&wxshare_count=1&tt_from=weixin&utm_source=weixin&utm_medium=toutiao_android&utm_campaign=client_share&share_token=4be8e961-bfa9-4702-8f10-61fed2b223f2&source=m_redirect

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/152235.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【设计一个缓存--针对各种类型的缓存】

设计一个缓存--针对各种类型的缓存 1. 设计顶层接口2. 设计抽象类 -- AbstractCacheManager3. 具体子类3.1 -- AlertRuleItemExpCacheManager3.2 -- AlertRuleItemSrcCacheManager 4. 类图关系 1. 设计顶层接口 // 定义为一个泛型接口,提供给抽象类使用 public interface Cach…

技术管理责任制度《三》

为了加强新时期科技档案的保密工作&#xff0c;确保档案在保管、利用、复制、销毁过程中的保密工作&#xff0c;特规定如下&#xff1a; 彩虹图纸管理软件_图纸管理系统_图纸文档管理软件系统_彩虹EDM【官网】 1、档案员要认真学习和严格执行国家有关安全、保密制度规定&#…

【java学习—十四】反射获取类的父类、接口、构造方法、方法(3)

文章目录 1. 通过反射获取一个类的父类和接口2. 反射获取一个类的构造方法3. 反射获取全部构造器4. 通过反射创建一个对象5. 反射机制获取类的方法 1. 通过反射获取一个类的父类和接口 使用反射可以取得&#xff1a; 实现的全部接口 public Class<?>[] getInterfaces(…

【小黑嵌入式系统第二课】嵌入式系统的概述(二)——外围设备、处理器、ARM、操作系统

上一课&#xff1a; 【小黑嵌入式系统第一课】嵌入式系统的概述&#xff08;一&#xff09;——概念、特点、发展、应用 下一课&#xff1a; 【小黑嵌入式系统第三课】嵌入式系统硬件平台&#xff08;一&#xff09;——概述、总线、存储设备&#xff08;RAM&ROM&FLASH…

优思学院|新版ISO9001:2015质量体系的优势(一)高阶结构

在全球商业环境中&#xff0c;不断提高产品和服务的质量至关重要。因此&#xff0c;国际标准组织&#xff08;ISO&#xff09;于2015年发布了更新的ISO 9001标准&#xff0c;即ISO 9001:2015质量体系标准。这一更新旨在适应不断变化的商业需求和挑战&#xff0c;为组织提供更强…

母婴行业数字化发展趋势:内容多元化、服务定制化、人群全覆盖

母婴行业数字化发展趋势&#xff1a;内容多元化、服务定制化、人群全覆盖 引言&#xff1a;时代的高速发展&#xff0c;在经济压力、生活节奏、婚育观念等多重因素的影响下&#xff0c;我国人口出生率自2016年&#xff08;人口出生数量统计1883万&#xff09;到2022年&#xf…

nn.Embedding()的原理

nn.Embedding()的原理&#xff1a; 定义一个Embedding&#xff1a; embeddings nn.Embedding(num_embeddings10, embedding_dim3)vocab_size : 10 输出维度为&#xff1a; 3 假定输入inputs如下&#xff1a; inputs torch.tensor([[1,3,6, 8],[9,1,3,5] ],dtypetorch.lo…

zabbix基本介绍 安装部署 页面访问

这里写目录标题 一、zabbix 监控1、zabbix 监控架构2、zabbix 监控报警渠道3、Zabbix 优点4、Zabbix 缺点5、Zabbix 监控系统监控对象6、Zabbix监控方式7、zabbix 架构1、Server2、数据库存储3、Web界面4、Proxy 代理服务器5、Agent监控代理6、数据流 8、Zabbix常用术语的含义1…

『Linux升级路』基本指令

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;Linux &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、认识操作系统 &#x1f4d2;1.1什么是操作系统 &#x1f4d2;1.2操作系统…

基于ssm的高校共享单车管理系统(有报告)。Javaee项目,ssm项目。

演示视频&#xff1a; 基于ssm的高校共享单车管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm项目。 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 项目介绍&…

torch_cluster、torch_scatter、torch_sparse三个包的安装

涉及到下面几个包安装的时候经常会出现问题&#xff0c;这里我使用先下载然后再安装的办法&#xff1a; pip install torch_cluster pip install torch_scatter pip install torch_sparse 1、选择你对应的torch版本&#xff1a;https://data.pyg.org/whl/ 2、点进去然后&…

智慧工地AI视频管理平台源码

智慧工地是指以物联网、移动互联网技术为基础&#xff0c;充分应用人工智能等信息技术&#xff0c;通过AI赋能建筑行业&#xff0c;对住建项目内人员、车辆、安全、设备、材料等进行智能化管理&#xff0c;实现工地现场生产作业协调、智能处理和科学管理。智慧工地的核心是以一…

HBase中的数据表是如何用CHAT进行分区的?

问CHA&#xff1a;HBase中的数据表是如何进行分区的&#xff1f; CHAT回复&#xff1a; 在HBase中&#xff0c;数据表是水平分区的。每一个分区被称为一个region。当一个region达到给定的大小限制时&#xff0c;它会被分裂成两个新的region。 因此&#xff0c;随着数据量的增…

[C++]:8.C++ STL引入+string(介绍)

C STL引入string(介绍&#xff09; 一.STL引入&#xff1a;1.什么是STL2.什么是STL的版本&#xff1a;2-1&#xff1a;原始版本&#xff1a;2-2&#xff1a;P. J 版本&#xff1a;2-3&#xff1a;RW 版本&#xff1a;2-4&#xff1a;SGL版本&#xff1a; 3.STL 的六大组件&…

并发编程之生产者消费者模型

什么是生产者消费者模型 生产者消费者模型是多线程中一个比较典型的模型。 打个比方&#xff1a;你是一个客户&#xff0c;你去超市里买火腿肠。 这段话中的 "你"就是消费者&#xff0c; 那么给超市提供火腿肠的供货商就是生产者。超市呢&#xff1f;超市是不是被…

php连接sqlserver 安装sqlserver 驱动windows系统

第一步下载Windows 上的 Microsoft ODBC Driver for SQL Server ODBC 驱动程序 Microsoft ODBC Driver for SQL Server 直接下载安装即可&#xff0c;安装后可查看安装版本 第二步&#xff1a;下载php_sqlsrv 驱动 安装解压后&#xff0c;会有对应php版本的驱动文件&#xf…

草图一键生成静态网页,看看这个开源项目

借助GPT-4V视觉模型&#xff0c;可以轻松的将一张草图生成一个静态页面。现在这已经不是什么稀奇事了。主要是分享一下它的Prompt&#xff0c;很简单&#xff0c;用户画好草图后&#xff0c;将草图保存成png图片&#xff0c;传给GPT-4V&#xff0c;然后GPT返回一个标准的HTML&a…

Navicat for mysql 无法连接到虚拟机的linux系统下的mysql

原创/朱季谦 最近在linux Centos7版本的虚拟机上安装了一个MySql数据库&#xff0c;发现本地可以正常ping通虚拟机&#xff0c;但Navicat则无法正常连接到虚拟机里的MySql数据库&#xff0c;经过一番琢磨&#xff0c;发现解决这个问题的方式&#xff0c;很简单&#xff0c;总共…

9.MyBatis-Plus

1、前期准备 a. 创建数据库 CREATE TABLE USER (id BIGINT(20)NOT NULL COMMENT 主键ID,NAME VARCHAR(30)NULL DEFAULT NULL COMMENT 姓名,age INT(11)NULL DEFAULT NULL COMMENT 年龄,email VARCHAR(50)NULL DEFAULT NULL COMMENT 邮箱,PRIMARY KEY (id) );INSERT INTO user…

亚马逊云科技云存储服务指南

文章作者&#xff1a;Libai 高效的云存储服务对于现代软件开发中的数据管理至关重要。亚马逊云科技云存储服务提供了强大的工具&#xff0c;可以简化工作流程并增强数据管理能力。 亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、开发案例、技术专栏…