jstack 监控工具

<%@ page import="java.util.Map"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html>
<head>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<title>服务器线程信息</title>
</head>
<body>
<pre>
<% 
for(Map.Entry<Thread, StackTraceElement[]> stackTrace : Thread.getAllStackTraces().entrySet()){
    Thread thread = (Thread)stackTrace.getKey();
    StackTraceElement[] stack = (StackTraceElement[])stackTrace.getValue();
    if(thread.equals(Thread.currentThread())){
        continue;
    }
    out.print("\n线程:"+thread.getName()+"\n");
    for(StackTraceElement element : stack){
        out.print("\t"+element+"\n");
    }
}
%>
</pre>
</body>
</html>

对于jstack日志,我们要着重关注如下关键信息
Deadlock:表示有死锁
Waiting on condition:等待某个资源或条件发生来唤醒自己。具体需要结合jstacktrace来分析,比如线程正在sleep,网络读写繁忙而等待
Blocked:阻塞
Waiting on monitor entry:在等待获取锁

如果说系统慢,那么要特别关注 Blocked,Waiting on condition
如果说系统的cpu耗的高,那么肯定是线程执行有死循环,那么此时要关注下Runable状态。



JVM 参数监控
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page language="java" import="java.lang.management.ManagementFactory"%>
<%@ page language="java" import="java.lang.management.MemoryPoolMXBean"%>
<%@ page language="java" import="java.lang.management.RuntimeMXBean"%>
<%@ page language="java" import="java.lang.management.GarbageCollectorMXBean"%>

<%@ page language="java" import="java.text.NumberFormat"%>
<%@ page language="java" import="java.text.SimpleDateFormat"%>
<%@ page language="java" import="java.util.Date"%>
<%@ page language="java" import="java.util.List"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%!
public String abb(long a, long b) {
	NumberFormat numberFormat = NumberFormat.getInstance();
	numberFormat.setMaximumFractionDigits(2);
	String result = numberFormat.format((double) a / (double) b * 100);
	// System.out.println("num1和num2的百分比为:" + result + "%");
	return result;
}

public String getString(String[] str){
	String ret="";
	for(String s:str){
		ret+=s+",";
	}
	return ret;
}

%>
<%
RuntimeMXBean rmb = ManagementFactory.getRuntimeMXBean();
Date d = new Date(rmb.getStartTime());
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = formatter.format( d);

List<MemoryPoolMXBean> s = ManagementFactory.getMemoryPoolMXBeans();
List<GarbageCollectorMXBean> gcm = ManagementFactory.getGarbageCollectorMXBeans();

%>
<table border="1">
<tr>
<td colspan="4">JVM health check(by sdc):</td>
</tr>
<tr>
<td>ContextClassLoader:</td>
<td colspan="2">:=<%=Thread.currentThread().getContextClassLoader() %></td>
<td>查询当前的ClassLoader,用于判断是否有重启现象</td>
</tr>
<tr>
<td>startTime:</td>
<td colspan="2">:=<%= dateString%></td>
<td>启动时间,用户判断是否自动重启,这个重启是进程级别的。</td>
</tr>
<tr>
<td colspan="4">Memory Check: "PS Old Gen" and "PS Perm Gen" is vary important(PS Old Gen和PS Perm Gen最为重要)</td>
</tr>
<tr >
<td>序号</td>
<td>最大容量</td>
<td>当前使用</td>
<td>最大百分比</td>
</tr>
<%
for (MemoryPoolMXBean ss : s) {
	//ss.getUsage();
	%>
	<tr >
<td><%=ss.getName() %></td>
<td><%=ss.getUsage().getMax() %>:(<%=abb(ss.getUsage().getMax(),1024*1024*100) %>M)</td>
<td><%=ss.getUsage().getUsed() %>:(<%=abb(ss.getUsage().getUsed(),1024*1024*100) %>M)</td>
<td><%=abb(ss.getUsage().getUsed(),ss.getUsage().getMax()) %>%</td>
</tr>
	<%
}
%>
<tr>
<td colspan="4">GC Check: PS MarkSweep is the best zero(PS MarkSweep最好是0)</td>
</tr>
<tr >
<td>名称</td>
<td>GC 内存区域</td>
<td>GC次数</td>
<td>GC时间</td>
</tr>
<%
for (GarbageCollectorMXBean gg : gcm) {
	//ss.getUsage();
	%>
	<tr >
<td><%=gg.getName() %></td>
<td><%=getString(gg.getMemoryPoolNames()) %></td>
<td><%=gg.getCollectionCount() %></td>
<td><%=gg.getCollectionTime() %>ns(<%=abb(gg.getCollectionTime(),1000*100) %>s)</td>
</tr>
	<%
}
%>
</table>
</body>
</html>




猜你喜欢

转载自blog.csdn.net/qq_35809876/article/details/76736285