簡體   English   中英

如何在堆中通過許多StackTraceElement模擬完整的gc

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM