jstat的小伙伴:找出system.gc的调用的小工具
場景分析
現場環境中,造成gc頻繁的可能性之一就是通過system.gc主動調用了gc。這種情況出現在開發人員業務代碼,或者是jdk自身的代碼中(例如nio)。我們可以通過jstat -gccause查看gc的原因,如果真的是system.gc,那么找出調用的代碼就是繼續解決問題的關鍵。
查看system.gc的調用
如果說查看代碼調用,那么jstack就是首選,仔細想想,代碼的觸發時機不定,怎么才能去在合適的時候打印堆棧呢,最簡單的想法就是定時的去調用,這個方法是有用的,只不過在頻繁調用的時候,是可以捕獲到的。可是萬一不頻繁調用呢。
當我們想知道自己的代碼在什么時候被調用,那么最好的方式就是在自己的方法里去打印堆棧。這樣就知道是誰調用的了,也不用擔心是調用的時機等等。
解決方案也就出來了,那就是在system.gc調用的時候順便打印一下堆棧。system是jdk的類,可以自己編寫一個system類替換掉jdk的,只不過不想用的時候還得改回來。為了靈活我們選擇動態修改字節碼。
字節碼改造
我們先想想打印堆棧的代碼
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();for (StackTraceElement element : stackTrace) {System.out.println(element);}現在呢,我們就在system.gc前調用這個方法。這里修改字節碼的方式,我們使用asm。
InsnList list = new InsnList();list.add(getLabelNode());list.add(new MethodInsnNode(INVOKESTATIC, "com/xp/agent/core/ThreadInfo", "getStack", "()V", false));insns.insert(list);修改完就大功告成。
細節補充
字節碼是改成了,但是我們的那個類路徑得讓加載system類的classloader(bootstrapclassloader)找到我們的類。否則會拋出classnotfind或者noclassdefineerror。這里我們通過增加配置文件的方式。
Agent-Class: com.xp.agent.main.Main Can-Redefine-Classes: true Can-Retransform-Classes: true Class-Path: trace-0.0.1-SNAPSHOT-common.jar asm-all-6.0_BETA.jar Created-By: Apache Maven 3.3.9 Build-Jdk: 1.8.0_121 Boot-Class-Path: trace-0.0.1-SNAPSHOT-agentcore.jar代碼地址
大佬如果喜歡,可以點個星鼓勵一下。
https://github.com/xpbob/lightTrace
總結
以上是生活随笔為你收集整理的jstat的小伙伴:找出system.gc的调用的小工具的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Intellij IDEA集成JProf
- 下一篇: spark学习:ContextClean