jvm调优 java_opt_JVM调优,程序员必须掌握的知识

调优之前,得知道什么样的对象会进入老年代

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线程在等待这把锁,导致锁的嵌套了

注意:

死锁后程序还能够正常运行,因为死锁只是单个线程死锁了而已,

但是你重复执行死锁的那个方法就会导致整个线程池不可用,那么其他方法就没有线程去执行了

c71118fe6fb93cd34b58cc57930b95cc.png

如何定位死锁

开发环境:

在开发的过程中,可以通过oracle的jdk,bin目录下的jvisualvm.exe查看是否死应用锁,且会发现有线程一直在休眠状态

7c98ef08c56135c950517781e32f86d1.png

生产环境:

1.可以通过jps命令查看当前运行的java程序的pid

4a35282f6bcb20aa8f877470e4521ade.png

2.通过jstack 228 > test.txt(当前程序的pid)命令,将内容打印到test文本,来查看程序是否死锁,以及程序的详细信息

3.打开打印出来的文本,搜索 "deadlock" 来判断是否产生死锁,如果搜索到就证明产生了死锁,下图这样,就代表产生了死锁

79db278f77d232a380b4884d4f2bf257.png

4.通过用户线程,在文本中搜索用户线程的名称,就可以大概定位到死锁的代码位置

ed46409e2880b94f9c2ec0ba591a3633.png

0e8079e368d1daea14bfc9f1a0d42cdb.png

a39bc9e778c2332108f7c00b059ac0cd.png

调优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 指定快照存储的路径

7e024597bbc62ac7b4d95bb7327f4207.png

当内存发生溢出的时候,java会通过参数自动打印快照到我们指定的路径,并且打印的快照都挺大的~

07a5ba8ba1a6dbc3d6152aeccf1c1879.png

接着通过oracle的jdk自带的jvisualvm.exe工具来打开这个快照

9af5ea9a7f53da84de55117057f168dd.png

打开之后就如下图这样,注意记录一下异常线程,然后打开显示线程

de48470370d9518edff0ff7f1a4dc42d.png

然后将下面的内容Copy到一个新文本文件中,方便我们定位错误

0bab3568dae85e3b7ba9261f6a89361a.png

接着搜索刚刚记录的异常名称,就可以大概定位到哪一行代码发生了内存溢出了

3850dca708e7f5cbd4ee53e436d17402.png

如何查看大对象是谁,首先点到类按钮,然后点击大小,就可以看到这个对象占了整个堆的99.5%的内存

020d705b22ffd70a1ac842962b5f7dad.png

接着双击byte[]对象,就可以发现byte[]对象是被ArrayList的所引用的

5ee5059245d360f5acffbe22f52c57e1.png

8ca3d7f92af66a1b928b02c050f8b9c3.png

内存泄漏怎么定位

其实和内存溢出一样定位

内存泄漏和内存溢出的区别

内存泄漏,对象不可被GC回收

内存溢出,对象会被GC进行回收

可以通过jstat -gcutil pid命令来查看对应java的进行GC情况,并且也可以通过此命令来查看异常是内存溢出还是内存泄漏了

看下图可以知道,内存溢出,Eden区和Old区是被回收掉了,但是内存泄漏Eden区和Old区是没有被回收

91b02206c320770c7cf3df323e2e618b.png

s0: 新生代survivor space0简称 就是准备复制的那块 单位为%

s1:指新生代s1已使用百分比,为0的话说明没有存活对象到这边

e:新生代eden(伊甸园)区域(%)

o:老年代(%)

ygc:新生代回收次数

ygct:minor gc耗时

fgct:full gc耗时(秒)

GCT: ygct+fgct 耗时

调优3.服务器CPU100%问题怎么去定位

1.首先通过 "top"命令,来查看哪些应用占用CPU内存过高

9da162330c4a9506ea07d59c7af8317b.png

2.通过ps -mp pid -o THREAD,tid,time命令,可以查看当前系统哪些程序占用CPU率比较高

注意:下图的TID是10进制的

ps -mp 2785 -o THREAD,tid,time

8a2e55ae6e20e8e549e2403c65039c0a.png

3.通过jstack pid 命令查看程序,用户线程的NID以及它的状态

jstack 2785 > a.txt 注意:2785是程序pid 不是线程id,且是将详细内容打印到a文本当中哦~

因为上图中的TID是10进制,所以我们要把他转换成16进制在进行查找

我们将上图中的TID为2802转成16进制为af2,所以我们直接在打印出来的文本去查找,af2即可找到那个方法占用率高

4b69d2a8887ba24359f2ed66e2191db8.png

cf2b859b0b4bffbc0c4a991f99caff2e.png

调优4.根据业务需求来进行调优

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值