温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

怎样进行JVM性能监控和调优

发布时间:2021-10-21 10:32:50 来源:亿速云 阅读:147 作者:柒染 栏目:大数据

这期内容当中小编将会给大家带来有关怎样进行JVM性能监控和调优,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

JVM调优是Java中比较重要的知识点,尤其是分析JVM和监控JVM运行状态。

1. JVM性能监控

1、定位系统问题

  • 依据

    • GC日志

    • 堆转储快照(heapdump/hprof文件)

    • 线程快照(threaddump/javacore文件)

    • 运行日志

    • 异常堆栈

  • 分析依据的工具

    • jps:显示指定系统内的所有JVM进程

    • jstat:收集JVM各方面的运行数据

    • jinfo:显示JVM配置信息

    • jmap:形成堆转储快照(heapdump文件)

    • jhat:分析heapdump文件

    • jstack:显示JVM的线程快照

    • jconsole

    • visualVM

说明:后边两种是具有图形化界面的。

2、jps(是其他所有命令的基础)

作用:列出所有的JVM虚拟机进程。

格式:jps -l

怎样进行JVM性能监控和调优

3、jstat(是没有GUI界面的情况下,在运行期定位JVM性能问题的首选)

作用:查看gc数据和类加载卸载数据

格式:jstat option PID interval count

意义:每隔interval毫秒做一次option,一共做count次

怎样进行JVM性能监控和调优

说明:加载了3683个类,总共占有4355.3字节;卸载了0个类,卸载的类的字节数为0,类的加载与卸载共花销3.16秒

更多的jstat的使用,参看http://my.oschina.net/skyline520/blog/304805

4、jinfo

作用:查看和运行期修改JVM的配置参数

格式:jinfo -flag parameter PID

怎样进行JVM性能监控和调优

说明:修改3732进程下的MaxTenuringThreshold参数值,但是windows下失败。

5、jmap

作用:生成堆转储快照和查看最占内存的元素,用于分析内存泄露问题

格式(生成堆转储快照):jmap -dump:format=b,file=文件名 PID

怎样进行JVM性能监控和调优

说明:结果自己去看,太多了

6、jhat

作用:分析堆转储快照(与jmap配合)

格式:jhat 文件名

怎样进行JVM性能监控和调优

注意:该工具是万不得已才用的。

推出命令使用"ctrl+c"

7、jstack

作用:生成线程快照,定位线程长时间卡顿的原因(线程间死锁、死循环、请求外部资源导致的长时间等待)

格式:jstack -l PID

怎样进行JVM性能监控和调优

说明:查看3732进程中的所有线程的堆栈信息

《深入理解Java虚拟机》的作者提供了一个工具jsp页面,使得我们可以在程序运行时,随时运行该jsp页面,来查看线程堆栈信息,代码如下:

1 <%@ page language="java">注意:代码中我注释掉一段,是因为想也查出当前线程的堆栈信息,作者并没有这个注释。 总结:JVM性能相关的6个常用的JDK命令jps:查询JVM中的所有进程,找出将要操作的PID,是所有命令的基础jstat:查看相应JVM进程的gc、类加载卸载信息,是没有GUI界面查看JVM运行数据的首选jinfo:查看和在运行期动态修改JVM配置参数jmap:生成堆转储快照和比较占内存的对象jhat:配合jmap分析堆转储日志,除非没有其他工具可做这个事儿,否则就不用该工具jstack:生成线程快照,定位线程长时间卡顿的原因(线程间死锁、死循环、请求外部资源导致的长时间等待)输出gc信息到控制台-XX:+PrintGCDetails:输出GC的详细信息-XX:+PrintGCTimeStamps:输出GC的时间信息-XX:+PrintGCApplicatonStoppedTime:GC造成的应用暂停的时间输出gc信息到文件以上三个参数在这里依旧适用-Xloggc:文件路径/gc.log:输出到文件   图形化的JVM性能监控 1、图像化的故障处理工具JconsolevisualVM2、Jconsole进入"E:\Java\jdk1.6\bin",双击"jconsole.exe",弹出如下框:说明:这里列出了所有的JVM进程,一个Jconsole进程,一个eclipse(PID:4684),这相当于jps命令。选中其中一个PID,假设选中了eclipse,双击,出现下图:(注:之后的各个叶签,都是每4秒刷新一次)"内存":相当于jstat -gc,在上图中的详细信息部分,该部分对应的信息就是头部图表部分所写的参数(这里是"整个堆"的情况),同时对应的也是右下角部分柱状图所选中的柱子(这里是"堆"),对于"非堆"指的就是"方法区"(或者称为"永久代")。当然,这里也可以选择时间范围来查看相应的信息。"类":相当于jstat -class,列出了装载类和卸载类的相关信息。"线程":相当于jstack,折线图显示了线程数目的变化情况,包括峰值线程数量、活动线程数量;左下角展示了所有线程名称。双击相应的线程名称"VM摘要":相当于jinfo最后,测试一下线程死锁的现象。代码如下: View Code执行main()方法,之后去查看"线程"标签,点击"检测死锁",如下:发现线程Thread-95和Thread-106死锁(彼此拥有对方想要的锁)分析:1)Integer缓存机制Integer.valueOf(int xxx),该方法为了减少对象的创建,节省内存,会将xxx转化成的Integer对象缓存起来,之后只要是相同的xxx,那么这个方法都会直接从缓存中取出对象来。假设代码中的Integer.valueOf(1)生成的对象是java.lang.Integer@987197,而Integer.valueOf(2)生成的对象是java.lang.Integer@15e293a,那么之后无论调用多少次Integer.valueOf(1),也无论是哪一个线程去调用该方法,返回的都只是同一个对象java.lang.Integer@987197。也就是说上边的这段代码中的Integer.valueOf(i)只会生成两个不同的对象,就是java.lang.Integer@987197和java.lang.Integer@15e293a,而这两个对象也就是我们的锁对象。2)死锁发生的时机假设线程"Thread-95"执行到其第一个synchronized块中时(假设刚刚获取了锁对象java.lang.Integer@987197),这时候CPU时间片切换给了线程"Thread-106",而"Thread-106"执行其第一个synchronized块(获取了锁对象java.lang.Integer@15e293a),之后"Thread-106"要执行第二个synchronized块儿来获取锁对象java.lang.Integer@987197,这时候就获取不到了,因为这个锁对象正被"Thread-95"所持有,于是"Thread-106"就阻塞在java.lang.Integer@987197这个锁对象上,这时,假设CPU时间片又切换给了"Thread-95",该线程要执行第二个synchronized块来获取java.lang.Integer@15e293a,就获取不到了,因为该锁对象已被"Thread-106"所持有3)结果"Thread-95"持有锁对象java.lang.Integer@987197,阻塞在锁对象java.lang.Integer@15e293a;"Thread-106"持有锁对象java.lang.Integer@15e293a,阻塞在锁对象java.lang.Integer@987197 3、visualVM是一块更加全面的GUI监视工具,包含很多插件(需要自己下载),具体的见《深入理解Java虚拟机(第二版)》  JVM调优 1、JVM的调优主要是内存的调优,主要调两个方面:各个代的大小垃圾收集器选择2、各个代的大小常用的调节参数-Xmx-Xms-Xmn-XX:SurvivorRatio-XX:MaxTenuringThreshold-XX:PermSize-XX:MaxPermSize原则在实际开发中,前台不要使用jsp,使用velocity等模板引擎技术不要引入无关的jar-XX:SurvivorRatio过大:对象在年轻代的存活时间变长,可能在年轻代就被回收掉而不必进入年老代,但是相应的复制的时候survivor区就会被占用更多的空间。-XX:SurvivorRatio过大:对象在年轻代的存活时间变短,可能会早早进入年老代而失去在年轻代被回收的机会,但是相应的复制的时候survivor区也就有更多内存了,这样可能会避免部分大对象直接进入年老代-XX:SurvivorRatio过大:Eden变大,Survivor变小,minor GC可能减少,但是由于suvivor减小了,所以如果minor GC存活下来的对象大于suvivor,则会直接进入年老代-XX:SurvivorRatio过小:Eden变小,Survivor变大,minor GC可能增多,但是由于suvivor变大了,能够存储更多存活下来的对象,进入年老代的对象可能会减少 调节时机:minor GC太频繁-Xmn过小:minor GC太频繁;小对象可能也会直接进入年老代,提前导致Full GC-Xmn过大:年轻代大了,minor GC的时间变长了;年老代变小了,Full GC会频繁调节策略:若-Xmx可调大,则调大,且保持-Xmn==-Xmx/4~-Xmx/3;若-Xmx不可调大,在保持-Xmn==-Xmx/4~-Xmx/3的范围内增大-Xmn,若-Xmn也不可调了,则试着调大-XX:SurvivorRatio来看看情况-Xmx==-Xms:防止堆内存频繁进行调整,调整的时机见《第一章 JVM内存结构》-Xmn:通常设为-Xmx/4(这是我在企业中实习时的设置方式,系统运行正常、平稳、速度也快),林昊推荐的是-Xmx/3,所以-Xmn==-Xmx/4~-Xmx/3-XX:SurvivorRatio:默认8-XX:MaxTenuringThreshold:默认为15-XX:MaxPermSize==-XX:PermSize3、垃圾收集器选择企业中最常用的两个组合:(这里由于大部分大型企业用的还是JDK1.6,所以G1不说)关于下边两组垃圾收集器的详细原理见:第五章 JVM垃圾收集器(1)Parallel Scavenge/Parallel Old注重吞吐量(吞吐量越大,说明CPU利用率越高)主要用于处理很多的CPU计算任务而用户交互任务较少的情况也用于让JVM自动调优而我们袖手旁观的情况(-XX:+UseParallelOldGC,-XX:GCTimeRatio,-Xmx,-XX:+UseAdaptiveSizePolicy)-XX:+UseParallelOldGC:指定使用该组合ParNew/CMS注重STW的缩短(该时间越短,用户体验越好,而且会减少部分请求的请求超时问题)-XX:+UseConcMarkSweepGC:指定使用该组合-XX:CMSInitiatingOccupancyFraction:来指定当年老代空间满了多少后(百分比)进行垃圾回收关于上边两种组合的说明一般而言,在企业中,机器的CPU数量都比较多,且CPU的计算能力也不会成为瓶颈,所以对于CMS的并发标记与并发清除阶段,会占用CPU资源的问题,其实不是大事儿;而对于Parallel的注重吞吐量的问题也就不是什么大事儿了,毕竟CPU是强大的所以,ParNew/CMS是首选(在G1不能用的情况下),Parallel Scavenge/Parallel Old只在想让JVM自动管理内存的情况下使用注意:在实际调优过程中,可以使用jstat、jconsole、visualVM或GC日志的检测数据来调,具体的示例见《深入理解java虚拟机(第二版)》p142对eclipse运行速度的调优。关于GC日志的参数含义与每一种垃圾收集器的GC日志的格式,查看《深入理解Java虚拟机(第二版)》的P89和《深入分析java web技术内幕(修订版)》的P224

上述就是小编为大家分享的怎样进行JVM性能监控和调优了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

jvm
AI