13-JVM调优实战-3

上一篇:12-JVM调优实战-2

今天来介绍一款阿里巴巴的调优工具。

Arthas详解

Arthas 是 Alibaba 在 2018 年 9 月开源的 Java 诊断工具。支持 JDK6+, 采用命令行交互模式,可以方便的定位和诊断线上程序运行问题。Arthas 官方文档十分详细,详见:https://arthas.aliyun.com/

1.Arthas使用场景

得益于 Arthas 强大且丰富的功能,让 Arthas 能做的事情超乎想象。下面仅仅列举几项常见的使用情况,更多的使用场景可以在熟悉了 Arthas 之后自行探索。

  1. 是否有一个全局视角来查看系统的运行状况?
  2. 为什么 CPU 又升高了,到底是哪里占用了 CPU ?
  3. 运行的多线程有死锁吗?有阻塞吗?
  4. 程序运行耗时很长,是哪里耗时比较长呢?如何监测呢?
  5. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
  6. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
  7. 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
  8. 有什么办法可以监控到 JVM 的实时运行状态?

2.Arthas使用

# github下载arthas
wget https://alibaba.github.io/arthas/arthas-boot.jar
# 或者 Gitee 下载
wget https://arthas.gitee.io/arthas-boot.jar

用java -jar运行即可,可以识别机器上所有Java进程(我们这里之前已经运行了一个Arthas测试程序,代码见下方)
在这里插入图片描述

package com.gwx.jvm;import java.util.HashSet;public class Arthas {private static HashSet hashSet = new HashSet();public static void main(String[] args) {// 模拟 CPU 过高cpuHigh();// 模拟线程死锁deadThread();// 不断的向 hashSet 集合增加数据addHashSetThread();}/*** 不断的向 hashSet 集合添加数据*/public static void addHashSetThread() {// 初始化常量new Thread(() -> {int count = 0;while (true) {try {hashSet.add("count" + count);Thread.sleep(1000);count++;} catch (InterruptedException e) {e.printStackTrace();}}}).start();}public static void cpuHigh() {new Thread(() -> {while (true) {}}).start();}/*** 死锁*/private static void deadThread() {/** 创建资源 */Object resourceA = new Object();Object resourceB = new Object();// 创建线程Thread threadA = new Thread(() -> {synchronized (resourceA) {System.out.println(Thread.currentThread() + " get ResourceA");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread() + "waiting get resourceB");synchronized (resourceB) {System.out.println(Thread.currentThread() + " get resourceB");}}});Thread threadB = new Thread(() -> {synchronized (resourceB) {System.out.println(Thread.currentThread() + " get ResourceB");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread() + "waiting get resourceA");synchronized (resourceA) {System.out.println(Thread.currentThread() + " get resourceA");}}});threadA.start();threadB.start();}
}

选择进程序号1,进入进程信息操作
在这里插入图片描述

输入dashboard可以查看整个进程的运行情况,线程、内存、GC、运行环境信息:
在这里插入图片描述

输入thread可以查看线程详细情况
在这里插入图片描述

输入 thread加上线程ID 可以查看线程堆栈
在这里插入图片描述

输入 thread -b 可以查看线程死锁
在这里插入图片描述

输入 jad加类的全名 可以反编译,这样可以方便我们查看线上代码是否是正确的版本
在这里插入图片描述

使用 ognl 命令可以
在这里插入图片描述

更多命令使用可以用help命令查看,或查看文档:https://arthas.aliyun.com/doc/commands.html

3.GC日志详解

对于java应用我们可以通过一些配置把程序运行过程中的gc日志全部打印出来,然后分析gc日志得到关键性指标,分析GC原因,调优JVM参数。
打印GC日志方法,在JVM参数里增加参数,%t 代表时间

-Xloggc:./gc-%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps  -XX:+PrintGCTimeStamps -XX:+PrintGCCause  
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M

Tomcat则直接加在JAVA_OPTS变量里。

3.1.如何分析GC日志

运行程序加上对应gc日志

java -jar -Xloggc:./gc-%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps  -XX:+PrintGCTimeStamps -XX:+PrintGCCause  
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M microservice-eureka-server.jar

下图中是我截取的JVM刚启动的一部分GC日志
在这里插入图片描述

我们可以看到图中第一行红框,是项目的配置参数。这里不仅配置了打印GC日志,还有相关的VM内存参数。
第二行红框中的是在这个GC时间点发生GC之后相关GC情况。

  1. 对于2.909: 这是从jvm启动开始计算到这次GC经过的时间,前面还有具体的发生时间日期。
  2. Full GC(Metadata GC Threshold)指这是一次full gc,括号里是gc的原因, PSYoungGen是年轻代的GC,ParOldGen是老年代的GC,Metaspace是元空间的GC
  3. 6160K->0K(141824K),这三个数字分别对应GC之前占用年轻代的大小,GC之后年轻代占用,以及整个年轻代的大小。
  4. 112K->6056K(95744K),这三个数字分别对应GC之前占用老年代的大小,GC之后老年代占用,以及整个老年代的大小。
  5. 6272K->6056K(237568K),这三个数字分别对应GC之前占用堆内存的大小,GC之后堆内存占用,以及整个堆内存的大小。
  6. 20516K->20516K(1069056K),这三个数字分别对应GC之前占用元空间内存的大小,GC之后元空间内存占用,以及整个元空间内存的大小。
  7. 0.0209707是该时间点GC总耗费时间。

从日志可以发现几次fullgc都是由于元空间不够导致的,所以我们可以将元空间调大点

java -jar -Xloggc:./gc-adjust-%t.log -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+PrintGCDetails -XX:+PrintGCDateStamps  
-XX:+PrintGCTimeStamps -XX:+PrintGCCause  -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M 
microservice-eureka-server.jar

调整完我们再看下gc日志发现已经没有因为元空间不够导致的fullgc了

对于CMS和G1收集器的日志会有一点不一样,也可以试着打印下对应的gc日志分析下,可以发现gc日志里面的gc步骤跟我们之前讲过的步骤是类似的

public class HeapTest {byte[] a = new byte[1024 * 100];  //100KBpublic static void main(String[] args) throws InterruptedException {ArrayList<HeapTest> heapTests = new ArrayList<>();while (true) {heapTests.add(new HeapTest());Thread.sleep(10);}}
}

CMS

-Xloggc:d:/gc-cms-%t.log -Xms50M -Xmx50M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+PrintGCDetails -XX:+PrintGCDateStamps  -XX:+PrintGCTimeStamps -XX:+PrintGCCause  -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC   

G1

-Xloggc:d:/gc-g1-%t.log -Xms50M -Xmx50M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+PrintGCDetails -XX:+PrintGCDateStamps  -XX:+PrintGCTimeStamps -XX:+PrintGCCause  -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -XX:+UseG1GC 

上面的这些参数,能够帮我们查看分析GC的垃圾收集情况。但是如果GC日志很多很多,成千上万行。就算你一目十行,看完了,脑子也是一片空白。所以我们可以借助一些功能来帮助我们分析,这里推荐一个gceasy(https://gceasy.io),可以上传gc文件,然后他会利用可视化的界面来展现GC情况。具体下图所示

在这里插入图片描述

上图我们可以看到年轻代,老年代,以及永久代的内存分配,和最大使用情况。
在这里插入图片描述

上图我们可以看到堆内存在GC之前和之后的变化,以及其他信息。
这个工具还提供基于机器学习的JVM智能优化建议,当然现在这个功能需要付费(其实,你把语言切换为:中文,就免费啦,世界如此简单,哈哈哈
在这里插入图片描述

4.JVM参数汇总查看命令

# 表示打印出所有参数选项的默认值
java -XX:+PrintFlagsInitial 
# 表示打印出所有参数选项在运行程序时生效的值
java -XX:+PrintFlagsFinal 

下一篇:14-JVM调优实战-常量池详解

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

约瑟夫环(循环列表实现)

约瑟夫&#xff08;Joseph&#xff09;问题的一种描述是&#xff1a;编号为1&#xff0c;2&#xff0c;3&#xff0c;…&#xff0c;n的n个人按顺时针方向围坐一圈。每人持有一个密码&#xff08;正整数&#xff09;。一开始任选一个正整数作为报数上限值m&#xff0c;从第一个…

docker使用(二)提交到dockerhub springboot制作镜像

docker使用&#xff08;二&#xff09; dockerhub创建账号创建存储库成功&#xff01;开始推送获取image名 提交成功SpringBoot项目制作Dockerfile镜像部署打jar包 dockerhub创建账号 &#xff08;自认为可以理解为github一类的东西&#xff09; 单击创建存储库按钮。 设定存…

uniapp 小程序 全局弹窗 每个需要使用的页面都不用再引用

文章目录 创建组件在项目的根目录下的vue.config.vue中配置页面中使用 使用全局组件&#xff0c;先声明全局组件 与普通的组件声明不同之处在于 1&#xff1a;目录形式 2&#xff1a;声明引用方式 创建组件 在components目录中创建组件目录/组件vue&#xff0c;如下 注意需要同…

面向Ai设计的Mojo编程语言支持下载,当前只有Linux系统版本

据了解&#xff0c;Mojo是Modular AI公司开发的专门面向AI设计的编程语言&#xff0c;号称比Python快68000倍。 Mojo现已开放本地下载运行&#xff0c;除了编译器之外&#xff0c;Mojo SDK还包括一整套开发者和IDE工具&#xff0c;并用来构建和迭代 Mojo应用。 公司方面表示&…

二.RocketMQ基础概念及名词说明

RocketMQ基础概念及名词说明 一&#xff1a;RocketMQ基本概念1.消息&#xff08;Message&#xff09;2.生产者(Producer)3.消费者(Consumer)4.分组(Group)&#xff1a;4.主题&#xff08;Topic&#xff09;5.标签&#xff08;Tag&#xff09;6.队列&#xff08;Queue&#xff0…

FFMPEG视频压缩与Python使用方法

一、简介 FFMPEG 是一个完整的&#xff0c;跨平台的解决方案&#xff0c;记录&#xff0c;转换和流音频和视频。 官网&#xff1a;https://ffmpeg.org/ 二、安装 1、Linux&#xff1a; sudo apt install ffmpeg 2、Mac: brew install ffmpeg 3、Windows: 下载文件&#…

Charles基础使用指南

##Charles 基本使用指南 Charles 在本地构建一个HTTP代理服务器&#xff0c;可以实现对HTTP、HTTPS请求的抓取&#xff0c;也就是我们常说的抓包&#xff0c;以及对请求响应的修改等。 Charles 官网地址 https://www.charlesproxy.com/ ###一、移动端的抓包实现 1. PC端开启…

C++重载输入和输出运算符

在C++中,标准库本身已经对左移运算符<<和右移运算符>>分别进行了重载,使其能够用于不同数据的输入输出,但是输入输出的对象只能是 C++ 内置的数据类型(例如 bool、int、double 等)和标准库所包含的类类型(例如 string、complex、ofstream、ifstream 等)。 …

UIScrollView setContentOffset: animated:

项目中遇到感觉一切都设置对了&#xff0c;但是看到的效果和预想的不一样。 后来查询了一番&#xff0c;才知道问题所在&#xff0c;现在记录一下&#xff0c;担心过后又忘了。 最初的问题是这样的&#xff0c;这个热度只有在评论里有&#xff0c;点击赞的时候&#xff0c;热度…

LeetCode:2. 两数相加

给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都不会以 0 …

如何使用ArcGIS去除卫星影像上的云

虽然目前发布的地图都是对云量进行过筛选&#xff08;一般低于20%&#xff09;&#xff0c;但是还是有可能会遇到有云的情况&#xff08;特别是下载历史影像的时候&#xff09;&#xff0c;那么这些云应该怎么去除呢&#xff0c;我们可以尝试使用ArcGIS进行处理。 识别像素 将…

数据结构--二叉树-堆(1)

文章目录 树概念相关的基本概念树的表示 二叉树概念特殊二叉树性质 堆二叉树的顺序结构堆的概念 堆的实现初始化数组初始化为堆向上调整向下调整插入删除打印、摧毁、判空、获取堆顶数据验证 堆的应用堆排序TopK问题 树 概念 树是一种常见的非线性的数据结构&#xff0c;&…

Mysql->Hudi->Hive

一 准备 1.启动集群 /hive/mysql start-all.sh2.启动spark-shell spark-shell \--master yarn \ //--packages org.apache.hudi:hudi-spark3.1-bundle_2.12:0.12.2 \--jars /opt/software/hudi-spark3.1-bundle_2.12-0.12.0.jar \--conf spark.serializerorg.apache.spark.…

自定义Dynamics 365实施和发布业务解决方案 - 7. 报表

在每个组织中,决策者都依赖于各种报告来推动业务取得成功。因此,每个软件开发项目都需要开发报告,Dynamics365配备了最先进的报告功能。这些报告的范围从简单的查询到具有复杂查询的更高级的报告。此外,Dynamics365的一个关键功能是其仪表板功能,它提供了一些不错的数据可…

Spring中Endpoint、HasFeatures、NamedFeature和Actuator的关系及实现原理

文章目录 1. 关系缘由2. Actuator简介及简单使用3. Endpoint和Actuator的关系4. Endpoint和HasFeatures的关系5. Endpoint和HasFeatures原理解析5.1 Endpoint的实现原理5.2 HasFeatures的实现原理 6. 个人闲谈 1. 关系缘由 我们经常可以在Springboot中看到Endpoint注解&#x…

Mysql binlog的三种模式statement,row,mixed详解,以及无主键造成复制延时的测试

2.1 Statement 模式的概念 Statement 是基于语句的复制模式。 Statement 模式将数据库中执行的修改操作记录为 SQL 语句&#xff0c;再从数据库上执行相同的 SQL 语句来实现数据同步。 2.2 Statement 模式的优点 Statement 模式的优点是简单明了&#xff0c;易于理解和实现。…

多线程的创建

一、基本概念 1 cpu CPU的中文名称是中央处理器&#xff0c;是进行逻辑运算用的&#xff0c;主要由运算器、控制器、寄存器三部分组成&#xff0c;从字面意思看就是运算就是起着运算的作用&#xff0c;控制器就是负责发出cpu每条指令所需要的信息&#xff0c;寄存器就是保存运…

双系统时间问题、虚拟机扩展空间问题

文献阅读计划&#xff1a; 首先要用ChatGPT查文献&#xff0c;用关键字查询&#xff0c;然后去搜索 add cyun 9.8 但是我发现好难搜啊&#xff0c;或者说相关的关键词搜不出来东西啊。不过师兄倒是搜的挺多的&#xff0c;这一点要再去好好学习一下 双系统时间问题&#xff1a…

LeetCode 50题:实现Pow(x,n)

题目 实现 pow(x, n) &#xff0c;即计算 x 的整数 n 次幂函数&#xff08;即&#xff0c;xn &#xff09;。 示例 1&#xff1a; 输入&#xff1a;x 2.00000, n 10 输出&#xff1a;1024.00000示例 2&#xff1a; 输入&#xff1a;x 2.10000, n 3 输出&#xff1a;9.26…