1. ClassNotFoundException/NoClassDefFoundError/NoSuchMethodException
参考关于类加载的博文即可,主要关注类加载的方式,类的版本等信息
2.Cpu us消耗高
是否是gc过于频繁,打开gc日志-Xloggc:./gc.log或者通过jstat -gcutil来查看gc和内存的情况,这种根据内存问题来处理
下面根据top -H -p/ jstack等命令查看是否有死锁,很深的循环或递归,也可能是序列化反序列化之类对象突然变大,计算突然增加
/**
* Created by itworker365 on 5/17/2017.
*/
public class CpuBusyTest implements Runnable{
public static void main (String[] args) {
for (int a = 0; a < 1000; a++) {
CpuBusyTest test = new CpuBusyTest();
Thread t = new Thread(test, "t-" + a);
t.start();
}
}
@Override
public void run() {
long start = System.currentTimeMillis();
long k = 0;
for (long i = 0; i < 2000000000; i++) {
k = 1 + i;
}
System.out.println(Thread.currentThread().getName() + "-----" + (System.currentTimeMillis() - start));
}
默认TOP按照进程显示,直接输入TOP看到占用最多的进程,如下,%CPU 99.8
top -H -p ID查看该进程下的线程情况,如果有一个特别高,可以找到PID,然后转换为16进制,比如2687-》0xA7F,打印进程堆栈 jstack ID在其中找到0xA7F
我的例子并没有对应,因为中间停掉了,所以意思明白就好,这里打印出jstack信息,找到对应的线程,查看他的状态。
一个出现死锁的例子
/**
* Created by itworker365 on 5/4/2017.
*/
public class LockTest {
private static String A = "A";
private static String B = "B";
public static void main (String[] args) {
new LockTest().deadlock();
}
private void deadlock () {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (A) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (B) {
System.out.println("AB");
}
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (B) {
synchronized (A) {
System.out.println("BA");
}
}
}
});
t1.start();
t2.start();
}
}
jstack之后显示deadlock信息
3. 内存问题
java.lang.OutOfMemoryError: Unable to create new native thread
用命令统计出当前总java线程数ps -eLf | grep java -c, 查出当前允许的最大句柄数ulimit -u,对比看是否正确,根据需要做出对应的调整,btrace找到哪里创建的线程@OnMethod(clazz="java.lang.Thread", method="start")
Executors.newCachedThreadPool这种来创建了一个没限制大小的线程池
java.lang.OutOfMemoryError: Heap Size或GC overhead limit exceeded
启动时加入-XX:+HeapDumpOnOutOfMemoryError在溢出时dump内存,之后再通过mat等工具再分析,通过btrace来定位代码
PermGen Space 跟踪class装载情况,用traceClassLoading或者btrace,@OnMethod(clazz="java.lang.ClassLoader", method="defineClass")
native OOM:Direct ByteBuffer(NIO)-XX:MaxDirectMemorySize=500m来实现当Direct ByteBuffer使用到500m后主动触发fgc来回收
到底什么算频繁,如果每隔10s或更短时间就来一次cms gc或full gc才算得上
jmap -dump:format=b,file=***log jhat ***.log或其他工具分析
jmap -histo打印加载的对象 jmap -histo:live来触发fgc
java.lang.OutOfMemoryError: Java heap space堆溢出,大对象多次没被回收,对比回收前后的内存使用量
*Error:递归,循环,局部变量过长,参数过多,局部变量作用域外没有释放等
java.lang.OutOfMemoryError: unable to create new native thread 操作系统没有足够的资源来创建线程,解决方法就是减少线程数量或者-Xss减小单个线程的大小
java.lang.OutOfMemoryError: PermGen space 类太多,是多个classloader或者太多反射动态加载类导致
4. Java进程crash或退出
默认情况下jdk会生成hs_err[pid].log的文件,core dump打开的话也会生成core dump文件
-XX:+PrintGCDetails
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/log/gcdump
遇到问题分而治之,隔离问题。将问题隔离到尽可能小的领域中,比如某个特定系统、特定版本、 甚至特定机器中。之后如果是java的问题,还可以继续分析是java应用、容器、或者jdk的问题,最后应该能确定到某个模块的某些代码、一次 commit、一行配置的问题。整个排查问题的过程就是一个从上到下,一步步缩小问题范围的过程。
状态数据大致可以分为两类:
一是监控类数据,收集这类数据对于应用的性能影响很小,基本可以忽略不计,所以可以持续收集,比如GC log,应用log等;
第二类是某些瞬时数据,这些数据要么收集的代价很大,很影响系统性能,要么时效性很高,过了故障点一切可能就都不一样了,所以不能 持续收集,必须迅速的在故障出现点自动采集,比如Heap dump,core dump等。