调优之前,得知道什么样的对象会进入老年代
1.大对象(当survivor区产生了大对象,则会进入老年代)
2.长期存活对象(对象一直在被引用着,年龄大于15,则会进入老年代)
3.空间担保对象(当瞬间新生代的空间满了,但是对象都被引用着,这个时候就会对象转到老年代中去)
4.动态年龄对象(当survivor区,对应的对象年龄如果50%大于survivor区的平均年龄则进入老年代)
什么时候会发生full gc
当我们的堆空间都放不下对象了,则会发生full GC,不过full GC会很慢,但是也是根据堆空间的大小来算回收时间的
调优1.如何定位死锁代码
产生死锁的原因
当一个线程在获取这把锁,另外一个线程在等待这把锁,这样就导致了锁的嵌套,如图
Thread-12线程获取了 "0x00000006c1c043f0" 这把锁,而nio-8080-exec-1用户线程等待这把锁,nio-8080-exec-1获取了"0x00000006c1c4f0d0"这把锁,而Thread-12线程在等待这把锁,导致锁的嵌套了
注意:
死锁后程序还能够正常运行,因为死锁只是单个线程死锁了而已,
但是你重复执行死锁的那个方法就会导致整个线程池不可用,那么其他方法就没有线程去执行了
如何定位死锁
开发环境:
在开发的过程中,可以通过oracle的jdk,bin目录下的jvisualvm.exe查看是否死应用锁,且会发现有线程一直在休眠状态
生产环境:
1.可以通过jps命令查看当前运行的java程序的pid
2.通过jstack 228 > test.txt(当前程序的pid)命令,将内容打印到test文本,来查看程序是否死锁,以及程序的详细信息
3.打开打印出来的文本,搜索 "deadlock" 来判断是否产生死锁,如果搜索到就证明产生了死锁,下图这样,就代表产生了死锁
4.通过用户线程,在文本中搜索用户线程的名称,就可以大概定位到死锁的代码位置
调优2.内存溢出怎么定位
首先内存溢出(oom)分为两种情况
1.内存溢出
2.内存泄漏
内存溢出怎么定位
有大对象的出现
看大对象被谁引用 通过线程快照 定位到哪一行出现
我这里学习的时候是配置了JVM参数,在IDEA里面设置的
windows: -Xloggc:D:\logs\gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\heapdump.dump
linx:java -jar -Xloggc:/usr/local/software/test/logs/gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/software/test/heapdump.dump jvm.jar
各个参数的意思是:
-Xloggc:打印日志到某个盘符下
-XX:+HeapDumpOnOutOfMemoryError 内存溢出时,打印堆内存快照
-XX:HeapDumpPath 指定快照存储的路径
当内存发生溢出的时候,java会通过参数自动打印快照到我们指定的路径,并且打印的快照都挺大的~
接着通过oracle的jdk自带的jvisualvm.exe工具来打开这个快照
打开之后就如下图这样,注意记录一下异常线程,然后打开显示线程
然后将下面的内容Copy到一个新文本文件中,方便我们定位错误
接着搜索刚刚记录的异常名称,就可以大概定位到哪一行代码发生了内存溢出了
如何查看大对象是谁,首先点到类按钮,然后点击大小,就可以看到这个对象占了整个堆的99.5%的内存
接着双击byte[]对象,就可以发现byte[]对象是被ArrayList的所引用的
内存泄漏怎么定位
其实和内存溢出一样定位
内存泄漏和内存溢出的区别
内存泄漏,对象不可被GC回收
内存溢出,对象会被GC进行回收
可以通过jstat -gcutil pid命令来查看对应java的进行GC情况,并且也可以通过此命令来查看异常是内存溢出还是内存泄漏了
看下图可以知道,内存溢出,Eden区和Old区是被回收掉了,但是内存泄漏Eden区和Old区是没有被回收
s0: 新生代survivor space0简称 就是准备复制的那块 单位为%
s1:指新生代s1已使用百分比,为0的话说明没有存活对象到这边
e:新生代eden(伊甸园)区域(%)
o:老年代(%)
ygc:新生代回收次数
ygct:minor gc耗时
fgct:full gc耗时(秒)
GCT: ygct+fgct 耗时
调优3.服务器CPU100%问题怎么去定位
1.首先通过 "top"命令,来查看哪些应用占用CPU内存过高
2.通过ps -mp pid -o THREAD,tid,time命令,可以查看当前系统哪些程序占用CPU率比较高
注意:下图的TID是10进制的
ps -mp 2785 -o THREAD,tid,time
3.通过jstack pid 命令查看程序,用户线程的NID以及它的状态
jstack 2785 > a.txt 注意:2785是程序pid 不是线程id,且是将详细内容打印到a文本当中哦~
因为上图中的TID是10进制,所以我们要把他转换成16进制在进行查找
我们将上图中的TID为2802转成16进制为af2,所以我们直接在打印出来的文本去查找,af2即可找到那个方法占用率高
网友评论