深入理解Java虚拟机(三)性能监控、优化

来源:互联网 发布:java 2017腾讯面试题 编辑:程序博客网 时间:2024/06/06 06:56

JVM性能监控

JDK的命令行工具

jps:虚拟机进程状况工具

它的功能也和ps命令类似:可以列出正在运行的虚拟机进程,并显示虚拟机执行主类(Main Class,main()函数所在的类)名称以及这些进程的本地虚拟机唯一ID(Local Virtual Machine Identifier,LVMID)。
jps可以通过RMI协议查询开启了RMI服务的远程虚拟机进程状态,hostid为RMI注册表中注册的主机名。参数:

jstat:虚拟机统计信息监视工具

用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据,在没有GUI图形界面,只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。

jinfo:Java配置信息工具

作用是实时地查看和调整虚拟机各项参数。使用-sysprops选项把虚拟机进程System.getProperties()的内容打印出来。

jmap:Java内存映像工具

map的作用并不仅仅是为了获取dump文件,它还可以查询finalize执行队列、Java堆和永久代的详细信息,如空间使用率、当前用的是哪种收集器等。

jhat:虚拟机堆转储快照分析工具

jhat内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,可以在浏览器中查看。

jstack:Java堆栈跟踪工具

用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等都是导致线程长时间停顿的常见原因。线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做些什么事情,或者等待着什么资源。

HSDIS:JIT生成代码反汇编

HSDIS是一个HotSpot虚拟机JIT编译代码的反汇编插件,它包含在HotSpot虚拟机的源码之中,但没有提供编译后的程序。

JDK的可视化工具

JConsole:Java监视与管理控制台

JConsole(Java Monitoring and Management Console)是一种基于JMX的可视化监视、管理工具。它管理部分的功能是针对JMX MBean进行管理,由于MBean可以使用代码、中间件服务器的管理控制台或者所有符合JMX规范的软件进行访问。

VisualVM:多合一故障处理工具

VisualVM(All-in-One Java Troubleshooting Tool)是到目前为止随JDK发布的功能最强大
的运行监视和故障处理程序。VisualVM的还有一个很大的优点:不需要被监视的程序基于特殊
Agent运行,因此它对应用程序的实际性能的影响很小,使得它可以直接应用在生产环境
中。

调优

  • Direct Memory:可通过-XX:MaxDirectMemorySize调整大小,内存不足时抛出OutOfMemoryError或者OutOfMemoryError:Direct buffer memory。
  • 线程堆栈:可通过-Xss调整大小,内存不足时抛出StackOverflowError(纵向无法分配,即无法分配新的栈帧)或者OutOfMemoryError:unable to create new native thread(横向无法分配,即无法建立新的线程)。
  • Socket缓存区:每个Socket连接都Receive和Send两个缓存区,分别占大约37KB和25KB内存,连接多的话这块内存占用也比较可观。如果无法分配,则可能会抛出IOException:Toomany open files异常。
  • JNI代码:如果代码中使用JNI调用本地库,那本地库使用的内存也不在堆中。
  • 虚拟机和GC:虚拟机、GC的代码执行也要消耗一定的内存。

修改配置文件eclipse.ini中参数,优化eclipse。虚拟机的运行数据通过VisualVM及其扩展插件VisualGC进行采集。

案例:
“堆大小”的曲线与“使用的堆”的曲线一直都有很大的间隔距离,每当两条曲线开始有互相靠近的趋势时,“最大堆”的曲线就会快速向上转向,而“使用的堆”的曲线会向下转向。“最大堆”的曲线向上是虚拟机内部在进行堆扩容,运行参数中并没有指定最小堆(-Xms)的值与最大堆(-Xmx)相等,所以堆容量一开始并没有扩展到最大值,而是根据使用情况进行伸缩扩展。“使用的堆”的曲线向下是因为虚拟机内部触发了一次垃圾收集,一些废弃对象的空间被回收后,内存用量相应减少,Java堆运作是完全正常的。
“PermGen大小”的曲线与“使用的PermGen”的曲线几乎完全重合在一起,这说明永久代中没有可回收的资源,所以“使用的PermGen”的曲线不会向下发展,永久代中也没有空间可以扩展,所以“PermGen大小”的曲线不能向上扩展。这次内存溢出很明显是永久代导致的内存溢出。

可以通过以下几个参数要求虚拟机生成GC日志:-XX:+PrintGCTimeStamps(打印GC停顿时间)、-XX:+PrintGCDetails(打印GC详细信息)、-verbose:gc(打印GC信息,输出内容已被前一个参数包括,可以不写)、-Xloggc:gc.log。
参数:
-XX:+DisableExplicitGC 屏蔽掉System.gc()
-Xverify:none 禁止掉字节码验证过程
-XX:MaxPermSize 指定永久代最大容量
-XX:PermSize 永久代初始容量
-Xms: 堆初始容量
-Xmx: 堆最大容量
-Xmn: 新生代的大小
-XX:NewSize=n: 设置新生代大小
-XX:NewRatio=n: 设置年轻代和年老代的比值。如:为3,表示新生代与年老代比值为1:3,新生代占整个新生代年老代和的1/4
-XX:SurvivorRatio=n: 新生代中Eden区与两个Survivor区的比值。注意Survivor区有两个,如:3,表示Eden:Survivor=3:2,一个Survivor区占整个新生代的1/5。

整个JVM内存大小=新生代大小 + 年老代大小 + 永久代大小。还要注意直接内存。

阅读全文
0 0
原创粉丝点击