2013-01-08 38 views
4

在這裏,我發現了一個問題,即同一個類的實例的大小是不是在不同版本的JVM相同的(它在1.6.0_21和 在1.6 .0_31)。儘管代碼是相同的。 你有沒有遇到過類似的問題?或者你有什麼建議?實例的大小在不同的JVM不同

JDK 1.6.0_21

# java -version 
java version "1.6.0_21" 
Java(TM) SE Runtime Environment (build 1.6.0_21-b06) 
Java HotSpot(TM) 64-Bit Server VM (build 17.0-b16, mixed mode) 

# java obj.ObjectSize & 

# jps | grep ObjectSize 
27251 ObjectSize 

# jmap -histo 27251 | grep US_ASCII 
145:    1    40 sun.nio.cs.US_ASCII 

JDK 1.6.0_31

# java -version 
java version "1.6.0_31" 
Java(TM) SE Runtime Environment (build 1.6.0_31-b04) 
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01, mixed mode) 

# java obj.ObjectSize & 

# jps | grep ObjectSize 
26645 ObjectSize 

# jmap -histo 26645 | grep US_ASCII 
161:    1    24 sun.nio.cs.US_ASCII 

ObjectSize.java

package obj; 
import java.util.concurrent.TimeUnit; 
import sun.nio.cs.US_ASCII; 

public class ObjectSize { 

    public static void main(String[] args) { 
     US_ASCII as = new US_ASCII(); 
     System.out.println(as); 

     try { 
      TimeUnit.MINUTES.sleep(5); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 
+4

這是怎麼對你的問題嗎? – nhahtdh

+0

如果我使用jre 1.6.0_21,則總內存使用量將大於使用1.6.0_31的總內存使用量。 –

+1

所以不要使用1.6.0_21。畢竟它是非常過時的。 –

回答

5

我想你遇到的只是原產於如何編寫一個事實編程語言的工作,特別是如果他們在虛擬機內運行。

中的更改虛擬機的執行被允許不同的行爲,例如只要他們保持同一個Java API- 生產不同大小的Java字節碼。

在內存中的用法區別真的有那麼大嗎?如果內存大小的增加實際上是一個問題,我敢建議你首先已經遇到內存問題。

如果你是在一個虛擬機50%的產能工作,現在打與其他我猜你需要在你的代碼進行一些更深層次的變化上限。或者在問題上投入更多硬件。 ;)的Java 6的

2

早期版本支持-XX:+UseCompressedOops,但它在默認情況下是關閉的。 (Java 6的第一個版本根本不支持這個)這意味着64位JVM中的引用是64位的。在較新的JVM中,如果堆爲< 32 GB,則使用32位參考。它可以做到這一點,因爲對象是8字節對齊的,所以你可以用32位引用尋址2^32 * 8字節。

注:US_ASCII從字符集

private final String name;   // tickles a bug in oldjavac 
private final String[] aliases;  // tickles a bug in oldjavac 
private Set<String> aliasSet = null; 

繼承三個字段這些參考文獻是4-字節較小節省12個字節,但對象是對齊,從而總的節約是16個字節8字節。

使用壓縮糟糕減少存儲器使用量。

Compressed oops in the Hotspot JVM

BTW:你不會直接使用這個類,而是你可以使用StandardCharset.US_ASCII

+1

['StandardCharsets'](http://docs.oracle.com/javase/7/docs/api/java/nio/charset/StandardCharsets.html)是在Java 7中添加的,因此它在您使用時不可用Java 6 –

+0

如果你不能使用StandardCharsets,你可以使用'Charset.forName(「US-ASCII」)'這是這個類在現實中的作用。 –

+1

感謝Peter Lawrey,我也在下面的鏈接中找到關於** - XX:+ UseCompressedOops **的鏈接。 [鏈接](http://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html)。 –

1

你有什麼建議嗎?

如果內存的使用對您來說很重要,請不要使用64位版本的1.6.0_21。切換到32位版本或更新的修補程序級別。或者更好,Java 7.畢竟1.6.0_21是非常過時的。

或者,運行JVM的選項,以明確地啓用壓縮糟糕如上所述here:所述6u23釋放之前

「對於JDK 6,使用-XX:+ UseCompressedOops標誌和java命令到啓用該功能「。

(但要注意,這可能發癢臭蟲在什麼是......那個時候......仍然是一個實驗JVM功能。)