2012-06-14 57 views
1

我想了解JVM堆大小如何與創建對象不同。Java:爲什麼在創建對象後JVM堆大小沒有區別

例如,如果您看到我的下面的程序,我在for循環中創建了10000個字符串對象,但在我的JVM環境中堆大小仍然沒有差異。

public class One { 

    public static void main(String args[]) { 

     long heapSizebefore = Runtime.getRuntime().totalMemory(); 
     System.out.println("heapSizebefore" + heapSizebefore); 

     for (int i = 0; i <= 10000; i++) { 
      String str = new String(); 

     } 

     long heapSizeafter = Runtime.getRuntime().totalMemory(); 
     System.out.println("heapSizeafter" + heapSizeafter); 

    } 

} 
+0

大多數OO程序有很多的成員方法,因爲你不能訪問成員變量或實現靜態方法,接口關閉這個功能。但是如果你不需要做那些事情,那麼靜態方法是有道理的。它告訴調用者「我只是一個函數;我不需要一個對象來做任何事情」。然而,沒有任何理由讓方法因爲內存而變成靜態的 - 你可能最終只是創建一個對象作爲參數傳遞,所以沒有節省。 –

+1

如果你想知道爲什麼我們在Java中使用靜態方法,爲什麼不問*這個問題呢?或者甚至更好,想一想問題,然後搜索「java靜態方法」,並閱讀其中的[many](http://stackoverflow.com/questions/2671496/java-when-to-use-static-methods ),[許多](http://stackoverflow.com/questions/538870/java-static-methods-best-practices),[重複](http://stackoverflow.com/questions/1618969/java-when-to -make-methods-static-v-instance)[](http://stackoverflow.com/questions/658407/static-methods)[it](http://stackoverflow.com/questions/3346764)。 –

+0

請注意,在這些問題上,我已經刪除了問題中關於靜態方法的部分。每個問題只有一個問題,StackOverflow可以更好地工作,恕我直言,這個頁面現在是一個有效答案的具體,可搜索問題的更好例子。如果您想提出有關現有問題未涉及的靜態方法的問題,請隨時創建一個新的問題。 –

回答

4

totalMemory的調用只是爲您提供了Java進程保留的內存量。這並不意味着它正在被堆中的對象積極填充。正如javadocs所說,對於當前的和未來的對象而言,它是可用的的可用的的總量。

事實上,Java會傾向於從底層操作系統請求大塊內存,而不是每次創建新對象時都要調用malloc(或同等版本)。

如果要跟蹤堆的實際大小,可以使用JConsole/JVisualVM等工具實時執行此操作,或者使用內存分析器進行更詳細的操作。如果您想以編程方式執行此操作,則需要爲複雜的東西註冊代理,但堆詳細信息通過JMX公開。查看java.lang:Memory MBean的HeapMemoryUsage屬性(這是JConsole用來顯示內存圖表的內容)。

2

JIT也可能優化整個for循環,因爲它沒有副作用。

2

兩個原因:

  1. 你測量的內存的量堆,不活動對象的大小之和保留
  2. 無論如何您都不會保留對分配字符串的引用,所以JVM可以隨時隨地收集垃圾收集。
0

基本上我想知道爲什麼我們在Java中使用靜態方法。

因爲靜態方法比實例方法簡單。

所以我的問題是保存內存(從對象創建)我們使用靜態方法??

不可以。您應該有目的地編碼,只創建您實際需要的東西。你需要的時候創建一個實例,當你不需要時創建一個實例。這不是出於性能原因,而是爲了減少代碼的概念權重。如果你必須維護你的代碼或者一些elses代碼,你需要找出爲什麼要完成某件事情,並且確定無意義的代碼真的毫無意義需要更長的時間。即尋找不在那裏的東西需要更長的時間,而不是尋找某種東西。


爲了支持多線程的存儲器分配,每個線程有一個線程局部分配緩衝器或TLAB

可用空間僅顯示公共池中有多少空閒空間,但是不會在每個線程的TLAB中可用大小。如果您分配足夠的字符串,則會在加載另一個塊時突然看到內存使用量突然增加。

你可以做的是-XX:-UseTLAB

// -XX:+UseTLAB heapUsedBefore: 5,368,848 heapUsedAfter: 5,368,848 
// -XX:-UseTLAB heapUsedBefore: 535,048 heapUsedAfter: 535,096 

public class One { 
    public static void main(String... args) { 
     Runtime runtime = Runtime.getRuntime(); 
     long heapUsedBefore = runtime.totalMemory() - runtime.freeMemory(); 

     String str = new String(); 

     long heapUsedAfter = runtime.totalMemory() - runtime.freeMemory(); 
     System.out.printf("heapUsedBefore: %,d heapUsedAfter: %,d%n", 
          heapUsedBefore, heapUsedAfter); 
    } 
} 
相關問題