您的位置:首页 > 运维架构

JVM 监控工具和调优工具

2017-09-17 10:30 417 查看

监控工具

1.jps

用来查看JVM里所有进程的具体状态 包括进程ID和进程的启动路径

常用参数
-l 输出完整打包包名称
-m 输出程序的命令行参数
-v 输出完整的JVM参数


2.jstack

1) 查看java程序崩溃的core文件 获得core文件的java stack和native stack的信息

2) 查看正在运行的java程序的native stack的信息

a) 查看运行程序呈现hung状态

b) 跟踪java的调用栈 剖析程序

常用指令
-l pid 打印锁的信息
-f pid 产生线程快照
-m pid 打印java和native栈的内容[混合模式]


3.jinfo

查看运行中的java程序的运行环境参数 包括java系统属性和JVM命令行参数;也可以从core文件里查看应用程序的配置信息

常用参数
-flag name 打印VM参数为name的值
-flag [+|-]name 启用或者禁用VM参数
-flag name=value 设置VM参数name为value
-flags 打印VM系统参数
-sysprops 打印系统属性
啥也不加   打印以上所有信息


4.jstat

利用JVM内建指令对应用程序的资源和性能进行实时的命令行监控,包括对Heap size和垃圾回收状态的监控

语法结构

Usage: jstat -help|-options
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]


参数解释

Options — 选项,我们一般使用 -gcutil 查看gc情况
vmid    — VM的进程号,即当前运行的java进程号
interval– 间隔时间,单位为秒或者毫秒
count   — 打印次数,如果缺省则打印无数次


具体的Options参数

-class:统计class loader行为信息
-compile:统计编译行为信息
-gc:统计jdk gc时heap信息
-gccapacity:统计不同的generations(不知道怎么翻译好,包括新生区,老年区,permanent区)相应的heap容量情况
-gccause:统计gc的情况,(同-gcutil)和引起gc的事件
-gcnew:统计gc时,新生代的情况
-gcnewcapacity:统计gc时,新生代heap容量
-gcold:统计gc时,老年区的情况
-gcoldcapacity:统计gc时,老年区heap容量
-gcpermcapacity:统计gc时,permanent区heap容量
-gcutil:统计gc时,heap情况


输出内容含义:

S0  — Heap上的 Survivor space 0 区已使用空间的百分比
S1  — Heap上的 Survivor space 1 区已使用空间的百分比
E   — Heap上的 Eden space 区已使用空间的百分比
O   — Heap上的 Old space 区已使用空间的百分比
P   — Perm space 区已使用空间的百分比
YGC — 从应用程序启动到采样时发生 Young GC 的次数
YGCT– 从应用程序启动到采样时 Young GC 所用的时间(单位秒)
FGC — 从应用程序启动到采样时发生 Full GC 的次数
FGCT– 从应用程序启动到采样时 Full GC 所用的时间(单位秒)
GCT — 从应用程序启动到采样时用于垃圾回收的总时间(单位秒)


5.jmap

观察运行中JVM物理内存的占用情况 包括HeapSize和MetaSpace等

常用参数

- heap 打印JVM堆的情况
-histo:打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。
-histo:live :同上,但是只答应存活对象的情况
-permstat:打印permanent generation heap情况


调优参数

参数名称含义默认值
-Xms初始堆大小物理内存的1/64(<1GB)默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制.
-Xmx最大堆大小物理内存的1/4(<1GB)1/4(<1GB) 默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制
-Xmn年轻代大小此处的大小是(eden+ 2 survivor space).与jmap -heap中显示的New gen是不同的。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小.增大年轻代后,将会减小年老代大小.此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8
-XX:NewSize设置年轻代大小
-XX:MaxNewSize设置年轻代大小
-XX:PermSize设置永久代的初始值物理内存的1/64
-XX:MaxPermSize设置永久代的最大值物理内存的1/4
-Xss每个线程的堆栈大小JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K.更具应用的线程所需内存大小进行 调整.在相同物理内存下,减小这个值能生成更多的线程.但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右 一般小的应用, 如果栈不是很深, 应该是128k够用的 大的应用建议使用256k。这个选项对性能影响比较大,需要严格的测试。和threadstacksize选项解释很类似,官方文档似乎没有解释,在论坛中有这样一句话:””-Xss is translated in a VM flag named ThreadStackSize”一般设置这个值就可以了。
说明:

Young GC

一般情况下,当生成新对象触发Eden区申请空间失败时,就会触发Minor GC,对Eden区记性GC,清除非存活对象,且把尚存活对象移动到空的Survivor区(To Survivor)。然后整理上次存放数据的Survivor(From Survivor) 将依然存活的对象放入To Survivor区。多次整理后还是存活且达到阈值(由 InitialTenuringThreshold 和 MaxTenuringThreshold 控制,默认值为7和15)就会上升到老年代。

Full GC

主要回收老年代的失效对象 一般同时触发整理年轻代

调优辅助工具

findclass.sh 用于查找特定类名出现在哪些jar包

#! /bin/bash

if [ $# -lt 2 ]; then
echo "Usage: $0 classname jar1 jar2..."
exit -1
fi

classname=$1
echo "Find Class: $classname"
shift

for file in $*
do
# echo $file
suffix=${file##*.}
if [ "x$suffix" == "xjar" ]; then

grepret=`jar -tf $file | grep $classname`
# echo $grepret
if [ "x$grepret" != "x" ]; then
echo "$file"
fi
fi

done


jps_kill.sh 用于kill指定类名的java进程

#! /bin/bash

TMP=/tmp/jps_kill.log

if [ $# -lt 1 ]
then
echo "Usage: $0 prog_name"
exit -1
fi

jps | grep -i $1 > $TMP

while read pid other
do
echo $pid
#echo $other

kill -9 $pid

done < $TMP


gcstat.sh 长期监控JVM的gc状况。

#!/bin/bash

PID=-1
INTERVAL=1000
NUM=60000000

if [[ $# -lt 1 ]]
then
echo "Usage: $0 <vmid> [<interval(ms)> [<count>]]"
exit 1
fi
PID=$1

if [[ $# -gt 1 ]]
then
INTERVAL=$2
fi

if [[ $# -gt 2 ]]
then
NUM=$3
fi

echo "$0 Start test...`date`"
echo

jstat  -gcutil -t -h50 $PID  $INTERVAL  $NUM

echo "$0 Finish test.`date`"


jmap_stat.sh 长期监控jmap状况。

#!/bin/bash

PID=-1
INTERVAL=3
NUM=60

if [[ $# -lt 1 ]]
then
echo "Usage: $0 <vmid> [<interval> [<count>]]"
exit 1
fi
PID=$1

if [[ $# -gt 1 ]]
then
INTERVAL=$2
fi

if [[ $# -gt 2 ]]
then
NUM=$3
fi

echo "$0 Start test...`date`"
echo

i=0
while [[ i -lt $NUM ]]
do
echo `date`
jmap -histo:live  $PID  | head -n 20

echo
sleep $INTERVAL

((i++))
done

echo "$0 Finish test.`date`"


调试辅助函数

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;

import java.io.File;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

public class JavaDebug{

public static int getPid() {
RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
String name = runtime.getName(); // format: "pid@hostname"
try {
return Integer.parseInt(name.substring(0, name.indexOf('@')));
} catch (Exception e) {
System.err.println(e.getMessage());
return -1;
}
}

public static void printEnv(){
Map<String,String> map = System.getenv();
Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator();
Map.Entry<String, String> entry;
while (iter.hasNext()) {
entry = iter.next();
String name = entry.getKey();
String value = entry.getValue();

System.out.println(name + ": "+ value);
}
}

public static void printProperties(){
Properties pros = System.getProperties();
pros.list(System.out);
}

public static String getPWD(){
return System.getProperty("user.dir");
}

public static void printSimpleMemoryInfo(){
Runtime runTime = Runtime.getRuntime();
System.out.println("Total Mem:" + runTime.totalMemory() + " Max Mem:" +runTime.maxMemory()
+ " Free mem:" + runTime.freeMemory() );
}

public static void printMemoryInfo(String info){
if( info != null){
System.out.println(info+ " JavaDebug:printMemoryInfo");
}

printSimpleMemoryInfo();
ExecCommand("jmap " + getPid());
}

public static void ExecCommand(String cmd){
System.out.println("Exec command: "+cmd);

try{
Process pro = null;
Runtime runTime = Runtime.getRuntime();
if (runTime == null) {
System.err.println("Create runtime false!");
throw new RuntimeException("Create runtime false!");
}

pro = runTime.exec(cmd);
BufferedReader input = new BufferedReader(new InputStreamReader(pro.getInputStream()));
PrintWriter output = new PrintWriter(new OutputStreamWriter(pro.getOutputStream()));
String line;
while ((line = input.readLine()) != null) {
System.out.println(line);
}
input.close();
output.close();
pro.destroy();
}
catch(IOException e) {
System.err.println(e.getMessage());
e.printStackTrace();
throw new RuntimeException("run command error!");
}

System.out.println("Exec command: "+cmd + " finish.");
}

public static void main(String[] args) throws Exception {
printProperties();

//printEnv();

System.out.println("========================");
int pid = getPid();
System.out.println("pid: " + pid);
System.out.println("pwd: " + getPWD());

printMemoryInfo(null);

ExecCommand("ls -l");
ExecCommand("jmap " + pid);

printMemoryInfo(null);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐