[英]how to emulate full gc by many StackTraceElement in heap
最近我的操作同事報告生產環境有很多全gc,影響app響應時間。 他提供了一個圖像
他特別說StackTraceElement有85M,並建議沒有這些代碼,例如
e.printStackTrace();
現在我想在我的本地模擬這種情況,並編寫如下的測試代碼
public class FullGCByLogTest {
private static final Logger log = Logger.getLogger(FullGCByLogTest.class);
public static final byte[] _1M = new byte[1 * 1024 * 1024]; //placeholder purpose
public static void main(String[] args) throws InterruptedException {
int nThreads = 1000; // concurrent count
ExecutorService pool = Executors.newFixedThreadPool(nThreads);
while (true) {
final CountDownLatch latch = new CountDownLatch(nThreads);
for (int i = 0; i < nThreads; i++) {
pool.submit(new Runnable() {
@Override
public void run() {
latch.countDown();
try {
latch.await(); // waiting for execute below code concurrently
} catch (InterruptedException e1) {
}
try {
int i = 1 / 0;
System.out.println(i);
} catch (Exception e) {
e.printStackTrace();
// log.error(e.getMessage(), e);
}
}
});
}
try {
Thread.sleep(100); // interval 1s every concurrent calling
} catch (InterruptedException e) {
}
}
}
}
我用這些vm args運行這個類
-Xmx4m -Xms4m -XX:NewSize=1m -XX:MaxNewSize=1m -XX:+PrintGCDetails
然后在jvisualvm VisualGC我發現舊的gen是7 M,但我設置的最大堆是4m。
另外在heapdump中我沒有找到StackTraceElement。 那我怎么能成功地模仿這個問題呢?
StackTraceElement
對象實際上是在實例化異常對象時創建的,一旦異常對象無法訪問,它們就有資格進行垃圾回收。
我懷疑你的(明顯的)存儲泄漏的真正原因是你的代碼中存在大量異常對象。
調用printStackTrace()
不會泄漏對象。 你的同事誤解了這個問題。 然而,在整個地方調用printStackTrace()
都是丑陋的...如果經常發生,那將導致性能問題。
您的模擬和結果是一個紅色的鯡魚,但是堆大於您要求的可能原因是JVM已經“舍入”到更大的堆大小。 (4Mb是一個微不足道的堆大小,對大多數Java程序來說都是不切實際的。)
那我怎么能成功地模仿這個問題呢?
仿真極不可能告訴你任何有用的東西。 您需要從生產系統中獲取堆轉儲並進行分析。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.