1. ClassNotFoundException/NoClassDefFoundError/NoSuchMethodException
参考关于类加载的博文即可,主要关注类加载的方式,类的版本等信息
https://www.cnblogs.com/baihuitestsoftware/articles/6382733.html
https://www.cnblogs.com/it-worker365/p/11269635.html
2.Cpu us消耗高
linux下获取占用CPU资源最多的10个进程,可以使用如下命令组合: 或者top进入后大写的M
//加标题去标题,第三列倒序排序
ps -aux | head -1 ; ps aux | grep -v PID | sort -rn -k +3 | head
//排序
ps -aux | sort -nr -k3 | head -10
是否是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. 内存问题
linux下获取占用内存资源最多的10个进程,可以使用如下命令组合:或者top进入后大写的P
ps -aux | head -1 ; ps aux | grep -v PID | sort -rn -k +4 | head
ps -aux | sort -nr -k4 | head -10
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堆溢出,大对象多次没被回收,对比回收前后的内存使用量
StackOverflowError:递归,循环,局部变量过长,参数过多,局部变量作用域外没有释放等
java.lang.OutOfMemoryError: unable to create new native thread 操作系统没有足够的资源来创建线程,解决方法就是减少线程数量或者-Xss减小单个线程的大小
java.lang.OutOfMemoryError: PermGen space 类太多,是多个classloader或者太多反射动态加载类导致
4.文件占用大小排序
du -s -h /* | sort -nr
5. 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等。