簡(jiǎn)介
在本文中找到有關(guān)于32位JVM和64位JVM之間的區(qū)別的一些常見(jiàn)問(wèn)題的答案。你將學(xué)到在這兩者之間進(jìn)行遷移時(shí)要考慮的所有事情,將有助于你更好地實(shí)施。
32位JVM和64位JVM之間存在一些明顯的區(qū)別和細(xì)微差別。我將嘗試通過(guò)此問(wèn)答文章來(lái)澄清它們。
我們是否需要了解32位JVM和64位JVM之間的區(qū)別?
如果你不是在構(gòu)建性能型Java服務(wù),則不必了解它們之間的區(qū)別。32位JVM和64位JVM之間的細(xì)微差別不會(huì)對(duì)你的Java服務(wù)產(chǎn)生太大影響。
64位JVM的性能是否優(yōu)于32位JVM?
我們大多數(shù)人認(rèn)為64位大于32位,因此64位JVM性能將優(yōu)于32位JVM性能。其實(shí)不然,事實(shí)并非如此。與32位JVM相比,64位JVM的性能可能會(huì)有所下降。以下是Oracle JDK文檔中有關(guān)64位JVM性能的摘錄:
`
通常,與在32位VM上運(yùn)行同一應(yīng)用程序相比,能夠處理大量?jī)?nèi)存的好處是64位VM的性能損失較小。當(dāng)你遷移到64位VM時(shí),將在64位平臺(tái)上運(yùn)行的應(yīng)用程序與在SPARC上的32位平臺(tái)運(yùn)行的應(yīng)用程序相比,性能差異降低了10-20%。在AMD64和EM64T平臺(tái)上,此差異范圍為0-15%,具體取決于訪問(wèn)應(yīng)用程序所執(zhí)行的指針的數(shù)量。”
如果性能受到影響,為什么有人會(huì)使用64位JVM?
在32位JVM中,最大可尋址內(nèi)存空間僅為2 ^ 32(即?4gb)。這意味著Java進(jìn)程的最大內(nèi)存大小不能超過(guò)4GB。實(shí)際上,由于各種其他限制(例如可用交換,內(nèi)核地址空間使用,內(nèi)存碎片和VM開(kāi)銷),該限制要低得多。下表總結(jié)了可以在32位JVM上設(shè)置的最大堆大小(即-Xmx):
操作系統(tǒng) | 最大堆 |
---|---|
AIX | 3.25 GB |
Solaris | 2 ~ 4 GB |
Linux | 2 ~ 3 GB |
Windows | 1.5 GB |
Mac OS X | 3.8 GB |
而如果你在64位JVM上運(yùn)行應(yīng)用程序,則最大可尋址內(nèi)存空間為2 ^ 64(即... 沒(méi)算出來(lái)--_--)。這意味著你的應(yīng)用程序的最大可尋址內(nèi)存大小接近無(wú)限。
`
為什么64位JVM性能可能比32位JVM慢
這是由于以下事實(shí):系統(tǒng)中的每個(gè)本機(jī)指針占用的是8個(gè)字節(jié)而不是4個(gè)字節(jié)。此額外數(shù)據(jù)的加載對(duì)內(nèi)存使用有影響,這取決于執(zhí)行過(guò)程中加載了多少個(gè)指針,從而導(dǎo)致執(zhí)行速度稍慢。
好消息是,由于以64位模式運(yùn)行的AMD64和EM64T平臺(tái),Java VM獲得了一些額外的寄存器,可用于生成更有效的本機(jī)指令序列。比較32位和64位執(zhí)行速度時(shí),這些額外的寄存器將性能提高到通常根本沒(méi)有性能損失的地步。
從32位JVM遷移到64位JVM時(shí)需要考慮哪些事項(xiàng)?
GC Stop World時(shí)間
從32位JVM遷移到64位JVM的主要原因是要獲得較大的堆大小(即-Xmx)。當(dāng)增加堆大小時(shí),GC暫停時(shí)間會(huì)自動(dòng)開(kāi)始變長(zhǎng),因?yàn)楝F(xiàn)在內(nèi)存中有更多垃圾需要清除。在進(jìn)行遷移之前,你需要進(jìn)行適當(dāng)?shù)腉C調(diào)整,否則,你的應(yīng)用程序可能會(huì)經(jīng)歷幾秒鐘到幾分鐘的暫停時(shí)間。于此同時(shí),有一個(gè)專門的GC分析網(wǎng)站可以供你去配置使用GCeasy
Native library
如果你的應(yīng)用程序使用Java本機(jī)接口(JNI)訪問(wèn)本機(jī)庫(kù),那么你還需要升級(jí)Native library,因?yàn)?2位JVM只能使用32位Native library。同樣,64位JVM只能使用64位Native library。
什么是CompressedOops?它與32位,64位JVM有關(guān)嗎?
是的,CompressedOOps與32位和64位JVM有關(guān)。
我們用數(shù)據(jù)字段定義對(duì)象。當(dāng)在內(nèi)存中創(chuàng)建該對(duì)象以及數(shù)據(jù)字段時(shí),還將創(chuàng)建對(duì)象標(biāo)頭。JVM需要對(duì)象標(biāo)頭來(lái)執(zhí)行內(nèi)部處理,虛擬方法調(diào)用,垃圾回收,鎖定等。
在32位JVM中,此對(duì)象標(biāo)頭占用8個(gè)字節(jié);在64 位JVM中,該對(duì)象標(biāo)頭占用16個(gè)字節(jié)。增加8個(gè)字節(jié)聽(tīng)起來(lái)可能并不多,但是鑒于你的應(yīng)用程序在其運(yùn)行時(shí)創(chuàng)建了數(shù)百萬(wàn)個(gè)對(duì)象,將8個(gè)字節(jié)乘以數(shù)百萬(wàn)個(gè)對(duì)象可能會(huì)增加可觀的開(kāi)銷。
你可以通過(guò)傳遞XX:+ UseCompressedOops JVM參數(shù)來(lái)緩解此問(wèn)題。當(dāng)你傳遞此參數(shù)時(shí),JVM會(huì)做出一個(gè)巧妙的技巧,并將對(duì)象標(biāo)頭的大小優(yōu)化為即使在64位中也僅使用12個(gè)字節(jié)。只要你的JVM堆大小(即-Xmx)小于32GB,此技巧就會(huì)起作用。如果超過(guò)32 GB,則對(duì)象標(biāo)頭大小將再次變?yōu)?6個(gè)字節(jié)。
注意:自Java SE 6u23及更高版本以來(lái),已將-XX:+ UseCompressedOops設(shè)置為默認(rèn)值。僅當(dāng)你在JDK 6u23或更早版本上運(yùn)行時(shí),才傳遞-XX:+ UseCompressedOopsargument。
什么時(shí)候應(yīng)該使用32位和64位JVM?
<2GB內(nèi)存
:如果你的應(yīng)用程序的堆大小(即-Xmx)小于2GB,則無(wú)需費(fèi)力地決定。使用32位JVM。
> 2GB內(nèi)存
:如果你的應(yīng)用程序需要2GB以上的內(nèi)存,那也不是明智的決定。使用64位JVM。但是,請(qǐng)進(jìn)行適當(dāng)?shù)男阅軠y(cè)試以衡量和減輕影響。
如何查找我的應(yīng)用程序是在32位還是64位JVM上運(yùn)行?
有一些選擇。讓我展示幾個(gè)選擇:
方法一:在命令提示符下,發(fā)出命令:
java -version
如果是64位JVM,你將看到輸出包含單詞:“64-Bit”。例:
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
如果它是32位JVM,則不會(huì)顯示單詞:“64-Bit”。例:
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) Client VM (build 25.211-b12, mixed mode)
方法二:你從Java程序發(fā)出以下語(yǔ)句:
System.out.println(System.getProperty("sun.arch.data.model") + "-bit JVM");
根據(jù)JVM類型,適當(dāng)?shù)陌姹緦⒈淮蛴≡诳刂婆_(tái)上。
我可以在64位操作系統(tǒng)上運(yùn)行32位JVM嗎?
有32位OS和64位OS。如果你在32位操作系統(tǒng)上運(yùn)行(這在今天很難找到),則只能運(yùn)行32位JVM。另一方面,如果你在64位操作系統(tǒng)上運(yùn)行,則可以在32位JVM或64位JVM上運(yùn)行應(yīng)用程序。
如何下載32位JVM或64位JVM?
轉(zhuǎn)到Oracle JDK下載頁(yè)面時(shí),將看到用于下載特定于你的操作系統(tǒng)的JDK的選項(xiàng):
如果你選擇x86,則將在此處下載32位JVM。如果選擇x64,則將下載64位JVM。
在32位JVM上編譯的代碼可以在64位JVM上運(yùn)行嗎?
我們使用javac即java編譯器將Java代碼編譯為字節(jié)代碼(即* .class文件)。生成的字節(jié)碼與32位和64位JVM無(wú)關(guān)。它可以在兩個(gè)JVM上運(yùn)行。記住Java古老的諾言:“Write once, run anywhere”。