2014-03-01 38 views
3

對於添加到Java應用程序的每個新類,內存方面的成本是多少?Java應用程序中每個類的成本 - 較少的大類或幾個較小的類

  • 是更好地擁有龐大的5000+線類或幾500-1000班線(如果所有的人都裝反正)
  • 對象實例每次,這是真的,唯一額外的內存使用情況用於實例變量引用
  • 對於沒有實例變量的5000行類,加載類時的成本範圍是多少?是粗略近似的類文件的大小?
  • jar文件的大小是否指示類將佔用的內存的通常大小或最大大小?

cruftex的回答後編輯: 這是我的階級分裂的理解:

  • 分成邏輯塊可以很好地提高了代碼的重用和 減少行數
  • 這也使得它更容易瞭解和 保持代碼

這是我的理解現在類加載:

  • 第一次使用類加載到存儲器(用於存儲是大致類文件的大小)
  • 如果使用JIT,一些額外的機器友好的二進制版本是由創建使用更多內存的JIT編譯器
  • 如果使用熱點,只有一些常用的類使用機器友好的版本進行了優化(以平衡內存和速度)
  • 一旦加載了類,創建其他實例的數量可以忽略不計開銷(大約50-100字節?)(假設沒有實例變量)
  • 一旦一個類加載的類本身永遠不會被垃圾收集

這是它大概是如何工作的?

+3

任何擁有5000+線條課程的人,尤其是如果有其他人需要維護的話,都應該退出並拍攝。這回答了你的問題了嗎?儘管如此,你認爲程序的成本是錯誤的。調試的主要成本很高,而且這種情況不會因過早和錯誤的優化而得到改善。如果你這樣編碼,你的尾巴就會有一隻老虎。 –

+0

內存成本應該相同或非常接近,因爲它取決於類內的對象。所以你可以通過做大量的課來節省一兩個字節,但代價是可讀性。小班更好IMO –

+0

我的應用程序中有幾個5,000多個班級。此外,有更多的短期班的做法令人沮喪。我試圖瞭解什麼是'正確的事情'來做! – Teddy

回答

2

對於添加到Java應用程序的每個新類,內存方面的成本是多少?

它通常沒有關係。一般而言,代碼以各種形式佔用整個內存使用量的很小比例(比如5%)。因此,即使您設法將代碼大小減少了一半,整體內存使用量也只會略有下降。

相反,過長的源文件會導致代碼庫很難導航,而較大的範圍使得難以概覽該類的具體內容以及某個更改是否安全。因此,長時間的源文件會使代碼的修改更加昂貴且容易出錯。

  • 第一次使用類加載到存儲器(使用的內存是大致類文件的大小)

正確。

  • 如果使用JIT,一些額外的機器友好的二進制版本由使用多一點的內存
  • 如果熱點只用一些常用的類的JIT編譯器創建與機優化 - 友好的版本(以平衡內存和速度)

熱點是JIT,所以你在這裏重複自己。但是,是的,JIT確實增加了代碼大小(但增加了更多的速度)。

一旦一個類被加載,創造更多的情況下具有可忽略的開銷(約50-100字節?)(假設沒有實例變量)

也就是說JVM具體。在Oracle熱點JVM,每個對象內存開銷大約是8個字節,如下面的程序演示:

public class Test { 
    public static void main(String[] args) { 
     Object[] array = new Object[10_000_000]; 
     Runtime rt = Runtime.getRuntime(); 
     long usedBefore = rt.totalMemory() - rt.freeMemory(); 
     for (int i = 0; i < array.length; i++) { 
      array[i] = new Object(); 
     } 
     long usedAfter = rt.totalMemory() - rt.freeMemory(); 
     System.out.println(usedBefore); 
     System.out.println(usedAfter); 
     System.out.println((double)(usedAfter - usedBefore)/array.length); 
    } 
} 
  • 一旦一個類被加載的類本身從不垃圾收集

雖然它不是Java語言規範所要求的,但是我曾經使用過的每個JVM在ClassLoader變得不可訪問時釋放一個類(授予,引導類加載器將始終保持可達,但自定義ClassLoader可能變爲unreac hable)。

+0

8字節超級低..真棒 – Teddy

4

你的問題不能回答具體問題,所以我試用一般的方法。你的問題針對的是內存消耗。但是,如果您節省內存,您的性能很可能會受到影響,這就是所謂的空間時間折衷。請參閱:http://en.wikipedia.org/wiki/Space%E2%80%93time_tradeoff

最簡單的方法來節省內存 - 如果你是只有有關你的程序大小 - 將完全關閉即時編譯器。這樣你可以保存你的java類的機器代碼的程序存儲空間。順便說一句:有很多VM選項會影響內存消耗!

是更好地擁有龐大的5000+線類或幾500-1000班線(如果所有的人都裝反正)

一般來說機會是更有可能的是,你可以重用代碼在更小的單位內更好。這意味着,當瞄準較小的尺寸時,您可能會節省代碼行。

如果代碼/方法保持不變並且只是在類之間分發它們,則會爲類添加額外開銷。

即使你問了三位專家,他們會看到代碼,他們會得到不同的答案,因爲它很大程度上取決於你的真實代碼,使用模式以及JIT在做什麼運行。

也就是說,即使是一個實驗也可能會導致您錯誤的方向,因爲您需要模擬相同的使用模式。

最後一個注意事項:看看您的虛擬機加載了多少個類,並決定是否真的值得保存視圖。

每次對象實例,這是真的,唯一額外的內存使用情況是實例變量引用

加上內存管理的一個恆定的開銷。

對於沒有實例變量的5000行類,加載類時的成本範圍是多少?是粗略近似的類文件的大小?

沒有JIT:是的。

jar文件的大小是否指示類將佔用的通常或最大內存大小?

不,完全沒有,因爲類只在需要的時候加載。

幾點建議:

如果你關心你的程序的內存使用情況,首先檢查堆兩次。我爲此推薦jmap和eclipse內存分析器。

然後,你可以看看你的類和方法。您可以調試JIT並查看編譯方法需要多少空間:-XX:-PrintCompilation。

+0

感謝您指出分解代碼可以減少由於重用而產生的線路。也瞭解JIT禁用作爲一種減少內存使用的方式,儘管我的情況並不那麼重要。我查了一下關於JIT的問題http://stackoverflow.com/questions/2903113/what-does-a-jit-compiler-do,並從那裏發表了關於JIT和熱點的文章http://www.ibm.com/ developerworks/java/library/j-jtp12214/ – Teddy