在这里,假设你已经读过《深入理解Java虚拟机》或者类似的书籍或查看过官方文档。

这个话题从为什么开始。

在虚拟机执行时,有时候会遇到各种线上问题。比如CPU使用居高不下,内存消耗过多,IO读写频繁等问题。我们得找到相应的方法来确定问题所在,再想出对策。

CPU占用问题

CPU占用高原因分析

原因a: 线程上下文切换消耗。

每个cpu或多核cpu中的一核,同一时间只能执行一个线程。在Java应用中,进行文件IO操作、网络IO操作、锁等待或者线程Sleep时,当前线程会进入阻塞或休眠状态,从而触发线程上下文切换,上下文切换过于频繁会造成内核占用过多的cpu资源,导致应用的响应变慢。

原因b:cpu上的运行队列。

每个核上处理runnable的线程的线程线反应其负载(load),load越大,核用越长的时间来完成。(建议每个核上load为1-3个)

原因c:cpu的利用率。

cpu利用率:用户进程、内核、中断处理、IO等待以及空闲五个部分组成。用户进程占用65-70%为宜,而内核占用为30-35%左右。

查看cpu使用情况工具

可用top或pidstat来查看cpu的使用情况。

top

使用top命令后,第三行为我们比较关注的信息。us(用户占用)、sy(系统占用)、ni(改变优先级占用)、id(空闲)。

对于多核cpu,可以按1显示每核的消耗情况。

以上默认为进程信息,如果要看线程信息,可以按shift+h来显示。

pidstat

此工具可以查看线程占用cpu情况,输入pidstat 1 2,表示在控制台上一秒输出一次,一共输出2次。可以多次查看。

分析cpu占用高的各种情况

us:用户占用高

top之后,发现us的百分比过高,表明应用消耗大部分cpu。我们得找到线程id,转换成16进制(linux上),再采用kill -3 [javapid]或jstack [javapid]来查看或dump导出查看。

当然,这部分占用高可能的原因是:线程一直处于runnable状态,通常是无阻塞、循环、正则或纯粹计算动作。

另一个可能是频繁的GC,最主要是Full GC。要从JVM内存消耗上查找原因。

sy:内核占用高

top之后,sy占用高,说明linux花费太多时间用于切换线程,造成这种情况主要原因是java应用启动的线程过多,且这些应用不断处于阻塞和执行状态变化之中,导致了操作系统要不断的进行线程上下文切换。按照上面的方法导出线程信息,查看线程状态、锁信息,找出等待状态或锁竞争过多的线程。

  1. 文件IO消耗

原因分析

在linux上,物理空闲内存够用,通常只有写文件时或者第一次读取文件时才会产生真正IO。

文件IO消耗的跟踪工具

pidstat

输入 pidstat -d -t - p [pid] 1 100,查看指定进程的io和额外信息。找到其中的io消耗高的线程,之后结合jstack来进一步分析,找到对应的java代码。

  1. 网线IO消耗

暂时略

  1. 内存消耗

内存消耗原因分析

多数生产情况下,通常将-Xms和-Xmx设为相同的值,避免运行期频繁申请内存。目前只有创建线程和使用Direct ByteBuffer时才会操作jvm堆外的内存。JVM内存消耗过多会导致GC执行频繁,CPU消耗增加。应用执行速度严重下降,严重会造成OutOfMemeryError,导致java进程退出。所以出现内存消耗过大问题时,根据以下详细分析,找出是jvm外的物理内存占用还是JVM Heap区。

如果os物理内存消耗过大,可能是JVM内存设置过大、创建的线程过多或Direct ByteBuffer往物理内存里放置过多的对象造成。

堆内存设置比物理内存大更容易出现问题。

Direct ByteBuffer是直接使用物理内存的,但是GC负责回收释放。

创建的线程数也会影响物理内存,这取决于-Xss值的大小,也取决于栈的深度。

内存查看工具

top

此工具查看的进行占用情况不太准,查看的为进程的占用全部内存。因为jvm启用时,会按照堆内存设置提前占据内存空间,但不表明在jvm里此内存已经被使用。

pidstat

pidstat -r -p [pid] [interval] [times],可查看指定进程的内存占用信息(包括物理内存和虚拟内存)。

程序执行慢的原因

锁竞争激烈

比较典型的是数据库连接池是有限的,而程序开太多的线程,那么有很多线程处于阻塞等待状态。

硬件资源未充分

这个好理解,多核CPU,只用单线程运行的话,无法充分发挥硬件优势。

数据量增长

这主要是相对数据库来说,若从1万条上升到1亿条,那么在查询时,应用程序多处在等待数据库给结果阶段。

那么知道以上原因和分析工具后,我们可以对jvm进行调优操作。

工具的常用命令:

jstack:

jstack [ option ] pid
jstack [ option ] executable core
jstack [ option ] [server-id@]remote-hostname-or-IP

1)、options:

executable Java executable from which the core dump was produced.

(可能是产生core dump的java可执行程序)

core 将被打印信息的core dump文件

remote-hostname-or-IP 远程debug服务的主机名或ip

server-id 唯一id,假如一台主机上多个远程debug服务

2)、基本参数:

-F当’jstack [-l] pid’没有相应的时候强制打印栈信息

-l长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表.

-m打印java和native c/c++框架的所有栈信息.

-h | -help打印帮助信息

pid 需要被打印配置信息的java进程id,可以用jps查询.

pidstat

pidstat [ 选项 ] [ <时间间隔> ] [ <次数> ]

常用的参数:

-u:默认的参数,显示各个进程的cpu使用统计
-r:显示各个进程的内存使用统计
-d:显示各个进程的IO使用情况
-p:指定进程号
-w:显示每个进程的上下文切换情况
-t:显示选择任务的线程的统计信息外的额外信息
-T { TASK | CHILD | ALL }
这个选项指定了pidstat监控的。TASK表示报告独立的task,CHILD关键字表示报告进程下所有线程统计信息。ALL表示报告独立的task和task下面的所有线程。
注意:task和子线程的全局的统计信息和pidstat选项无关。这些统计信息不会对应到当前的统计间隔,这些统计信息只有在子线程kill或者完成的时候才会被收集。
-V:版本号
-h:在一行上显示了所有活动,这样其他程序可以容易解析。
-I:在SMP环境,表示任务的CPU使用率/内核数量
-l:显示命令名和所有参数

JVM调优(一)底层原理分析和问题定位相关推荐

  1. java虚拟机线程调优与底层原理分析_Java并发编程——多线程的底层原理

    " Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,Java中所使用的并发机制依赖于JVM的实现和 CPU的 ...

  2. java虚拟机线程调优与底层原理分析_啃碎并发(七):深入分析Synchronized原理...

    原标题:啃碎并发(七):深入分析Synchronized原理 前言 记得开始学习Java的时候,一遇到多线程情况就使用synchronized,相对于当时的我们来说synchronized是这么的神奇 ...

  3. JVM 调优实战--使用jstack分析线程执行情况

    目录 jstack的使用 线程的6种状态 使用jstack分析死锁示例 jstack的使用 jstack命令可以直接输出每个线程的执行情况. 线程的6种状态 超时等待状态和等待状态的区别: 超时等待状 ...

  4. JVM 调优 2:GC 如何判断对象是否为垃圾,三色标记算法应用原理及存在的问题?

    文章目录 前言 一.如何判断一个对象是否为垃圾? 1.1.reference count(引用计数) 1.2.reference count(引用计数)存在的问题 二.Root Searching(根 ...

  5. java知识点8——垃圾回收原理和算法、通用的分代垃圾回收机制、 JVM调优和Full GC、开发中容易造成内存泄露的操作

    垃圾回收原理和算法 内存管理 Java的内存管理很大程度指的就是对象的管理,其中包括对象空间的分配和释放. 对象空间的分配:使用new关键字创建对象即可 对象空间的释放:将对象赋值null即可 垃圾回 ...

  6. JVM从入门到精通(七):GC常用参数,Method Area,JVM调优案例分析

    GC常用参数 -Xmn -Xms -Xmx -Xss 年轻代 最小堆 最大堆 栈空间 -XX:+UseTLAB 使用TLAB,默认打开 -XX:+PrintTLAB 打印TLAB的使用情况 -XX:T ...

  7. jvm原理及性能调优系列(jvm调优)

    jvm原理及性能调优系列(jvm调优) JVM设置: 1.设置合适的最大堆内存(新生代和老生代的最大和值)和最小堆内存(jvm启动时占用的操作系统内存大小),及设置好堆的比例分配. 2.设置合适的新生 ...

  8. JVM调优,面到了阿里性能优化师!

    小K 菜哥,我看你朋友圈,你好像换工作了? 菜哥 对啊,前阵子被产品经理烦的头疼,就想换工作了.刚好找到一个不错的. 小K 给我说说呗,让我也参考一下,我现在工资才15K,主管死坑,我也想换工作了 菜 ...

  9. 面试又栽在JVM调优上了!

    很多人都是抱着旁观者的心态看关于jvm的文章,给个镜子看看你们的嘴脸- 那我今天要来和你们过过招了,前几天我在知乎上看到一个叫做为什么要学习jvm的话题下回答虽然寥寥无几,却成了大型打脸现场... 想 ...

最新文章

  1. Windows 64位机上C/C++代码静态检查工具Logiscope RuleChecker的安装和使用
  2. java transient关键字_小伙子,你真的搞懂 transient 关键字了吗?
  3. MVC 源码系列之路由(一)
  4. Apache Hadoop版本详解
  5. Win10 使用minikube搭建k8s集群 并运行hello-minikube实例
  6. Linux下CMake简明教程(五)正规一点的组织结构
  7. mac 使用brew卸载安装node
  8. shu函数php,【函数分享】每日PHP函数分享(2021-3-3)
  9. 【漫画详解】用iframe障眼法,骗取用户点击
  10. 解决pre-commit hook failed (add --no-verify to bypass)的问题
  11. R60笔记本电脑风扇清理加油过程
  12. WordPress纯代码纯静态开启七牛CDN并集成七牛缩略图和水印功能
  13. 全球最专业的技术媒体,如何复盘 2019 AI 的发展?
  14. 【天天读书】2023 年,科技行业的创业者们推荐这 47 本书 | 创始人书单
  15. bzoj1022 约翰的游戏 反SG-博弈
  16. 华为云ECS下安装MySQL
  17. Real World Games Look Like Spinning Tops (DeepMind NIPS2020) 论文阅读记录
  18. oracle数据库主机CPU使用率高问题的分析及SQL优化
  19. linux硬件级虚拟机系统 电脑安桌游戏多开完全去除vm标识去虚拟化
  20. 《乔布斯传》圈点(末篇)

热门文章

  1. 采宝支付携手 - 打造O2O支付全新生态
  2. 人工智能和机器学习之间的区别
  3. php集成微信支付后台app端
  4. .NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。
  5. linux系统取消休眠,Linux关闭休眠和屏保模式
  6. 给React初学者的10分钟ES6教程
  7. NB-IoT智慧电表解决方案
  8. 第78届中国教育装备展示会即将在重庆开幕,亮点来了!
  9. 筑起网络信息安全防护
  10. 自闭症是广告敏感词?_我帮助建立了一个向自闭症儿童教授手语的机器人。 这是我学到的。...