

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、<p><b> Java 堆</b></p><p> Java 堆,每個(gè) Java 對(duì)象在其中分配,是您在編寫 Java 應(yīng)用程序時(shí)使用最頻繁的內(nèi)存區(qū)域。JVM 設(shè)計(jì)用于將我們與主機(jī)的特性隔離,所以將內(nèi)存當(dāng)作堆來考慮再正常不過了。您一定遇到過 Java 堆 OutOfMemoryError ,它可能是由于對(duì)象泄漏造成的,也可能是因?yàn)槎训拇笮〔蛔阋源鎯?chǔ)所有
2、數(shù)據(jù),您也可能了解這些場(chǎng)景的一些調(diào)試技巧。但是隨著您的 Java 應(yīng)用程序處理越來越多的數(shù)據(jù)和越來越多的并發(fā)負(fù)載,您可能就會(huì)遇到無法使用常規(guī)技巧進(jìn)行修復(fù)的OutOfMemoryError。在一些場(chǎng)景中,即使 java 堆未滿,也會(huì)拋出錯(cuò)誤。當(dāng)這類場(chǎng)景發(fā)生時(shí),您需要理解 Java 運(yùn)行時(shí)環(huán)境(Java Runtime Environment,JRE)內(nèi)部到底發(fā)生了什么。</p><p> Java 應(yīng)用程序在 J
3、ava 運(yùn)行時(shí)的虛擬化環(huán)境中運(yùn)行,但是運(yùn)行時(shí)本身是使用 C 之類的語(yǔ)言編寫的本機(jī)程序,它也會(huì)耗用本機(jī)資源,包括本機(jī)內(nèi)存。本機(jī)內(nèi)存是可用于運(yùn)行時(shí)進(jìn)程的內(nèi)存,它與 Java 應(yīng)用程序使用的 java 堆內(nèi)存不同。每種虛擬化資源(包括 Java 堆和 Java 線程)都必須存儲(chǔ)在本機(jī)內(nèi)存中,虛擬機(jī)在運(yùn)行時(shí)使用的數(shù)據(jù)也是如此。這意味著主機(jī)的硬件和操作系統(tǒng)施加在本機(jī)內(nèi)存上的限制會(huì)影響到 Java 應(yīng)用程序的性能。</p><p
4、><b> 硬件限制</b></p><p> 本機(jī)進(jìn)程遇到的許多限制都是由硬件造成的,而與操作系統(tǒng)沒有關(guān)系。每臺(tái)計(jì)算機(jī)都有一個(gè)處理器和一些隨機(jī)存取存儲(chǔ)器(RAM),后者也稱為物理內(nèi)存。處理器將數(shù)據(jù)流解釋為要執(zhí)行的指令,它擁有一個(gè)或多個(gè)處理單元,用于執(zhí)行整數(shù)和浮點(diǎn)運(yùn)算以及更高級(jí)的計(jì)算。處理器具有許多寄存器 —— ??焖俚膬?nèi)存元素,用作被執(zhí)行的計(jì)算的工作存儲(chǔ),寄存器大小決定
5、了一次計(jì)算可使用的最大數(shù)值。</p><p> 處理器通過內(nèi)存總線連接到物理內(nèi)存。物理地址(處理器用于索引物理 RAM 的地址)的大小限制了可以尋址的內(nèi)存。例如,一個(gè) 16 位物理地址可以尋址 0x0000 到 0xFFFF 的內(nèi)存地址,這個(gè)地址范圍包括 2^16 = 65536 個(gè)惟一的內(nèi)存位置。如果每個(gè)地址引用一個(gè)存儲(chǔ)字節(jié),那么一個(gè) 16 位物理地址將允許處理器尋址 64KB 內(nèi)存。</p>
6、<p> 處理器被描述為特定數(shù)量的數(shù)據(jù)位。這通常指的是寄存器大小,但是也存在例外,比如 32 位 390 指的是物理地址大小。對(duì)于桌面和服務(wù)器平臺(tái),這個(gè)數(shù)字為 31、32 或 64;對(duì)于嵌入式設(shè)備和微處理器,這個(gè)數(shù)字可能小至 4。物理地址大小可以與寄存器帶寬一樣大,也可以比它大或小。如果在適當(dāng)?shù)牟僮飨到y(tǒng)上運(yùn)行,大部分 64 位處理器可以運(yùn)行 32 位程序。</p><p><b> 操作系
7、統(tǒng)和虛擬內(nèi)存</b></p><p> 如果您編寫無需操作系統(tǒng),直接在處理器上運(yùn)行的應(yīng)用程序,您可以使用處理器可以尋址的所有內(nèi)存(假設(shè)連接到了足夠的物理 RAM)。但是要使用多任務(wù)和硬件抽象等特性,幾乎所有人都會(huì)使用某種類型的操作系統(tǒng)來運(yùn)行他們的程序。</p><p> 在 Aix 等多任務(wù)操作系統(tǒng)中,有多個(gè)程序在使用系統(tǒng)資源。需要為每個(gè)程序分配物理內(nèi)存區(qū)域來在其中運(yùn)行???/p>
8、以設(shè)計(jì)這樣一個(gè)操作系統(tǒng):每個(gè)程序直接使用物理內(nèi)存,并且可以可靠地僅使用分配給它的內(nèi)存。一些嵌入式操作系統(tǒng)以這種方式工作,但是這在包含多個(gè)未經(jīng)過集中測(cè)試的應(yīng)用程序的環(huán)境中是不切實(shí)際的,因?yàn)槿魏纬绦蚨伎赡芷茐钠渌绦蚧蛘卟僮飨到y(tǒng)本身的內(nèi)存。</p><p> 虛擬內(nèi)存 允許多個(gè)進(jìn)程共享物理內(nèi)存,而且不會(huì)破壞彼此的數(shù)據(jù)。在具有虛擬內(nèi)存的操作系統(tǒng)(比如 Windows、Linux 和許多其他操作系統(tǒng))中,每個(gè)
9、程序都擁有自己的虛擬地址空間 —— 一個(gè)邏輯地址區(qū)域,其大小由該系統(tǒng)上的地址大小規(guī)定(所以,桌面和服務(wù)器平臺(tái)的虛擬地址空間為 31、32 或 64 位)。進(jìn)程的虛擬地址空間中的區(qū)域可被映射到物理內(nèi)存、文件或任何其他可尋址存儲(chǔ)。操作系統(tǒng)可以將物理內(nèi)存中的數(shù)據(jù)移動(dòng)到未使用的交換區(qū),以便于最充分地利用物理內(nèi)存。當(dāng)程序嘗試使用虛擬地址訪問內(nèi)存時(shí),操作系統(tǒng)結(jié)合片上硬件將該虛擬地址映射到物理位置。該位置可以是物理 RAM、文件或交換區(qū)。如果一個(gè)內(nèi)存
10、區(qū)域被移動(dòng)到交換空間,那么它將在被使用之前加載回物理內(nèi)存中。</p><p> 在 AIX 上,進(jìn)程是關(guān)于 OS 控制資源(比如文件和套接字信息)、虛擬地址空間以及至少一個(gè)執(zhí)行線程的一系列信息。雖然 32 位地址可以引用 4GB 數(shù)據(jù),但程序不能獨(dú)自使用整個(gè) 4GB 地址空間。與其他操作系統(tǒng)一樣地址空間分為多個(gè)部分,程序只能使用其中的一些部分;其余部分供操作系統(tǒng)使用。與 Windows 和 Linux 相比,A
11、IX 內(nèi)存模型更加復(fù)雜并且可以更加精確地進(jìn)行優(yōu)化。AIX 32 位內(nèi)存模型被分成 16 個(gè) 256MB 分段進(jìn)行管理。</p><p> 用戶程序只能直接控制 16 個(gè)分段中的 12 個(gè) — 即 4GB 中的 3GB。最大的限制是,本機(jī)堆和所有線程棧都保存在分段 2 中。為了適應(yīng)對(duì)數(shù)據(jù)需求較高的程序,AIX 提供了一個(gè)大內(nèi)存模型。</p><p> 大內(nèi)存模型允許程序員或用戶附加一些共
12、享/映射分段作為本機(jī)堆使用,通過在構(gòu)建可執(zhí)行程序時(shí)提供一個(gè)鏈接器選項(xiàng)或者在程序啟動(dòng)之前設(shè)置 LDR_CNTRL 環(huán)境變量。要在運(yùn)行時(shí)支持大內(nèi)存模型,需要設(shè)置 LDR_CNTRL=MAXDATA=0xN0000000。其中, N 位于 1 和 8 之間。超過此范圍的任何值都會(huì)造成操作系統(tǒng)使用默認(rèn)內(nèi)存模型。在大內(nèi)存模型中,本機(jī)堆從分段 3 開始;分段
13、2 僅用于原始(初始)線程棧。</p><p> 當(dāng)您使用大內(nèi)存模型時(shí),分段分配是靜態(tài)的;也就是說,如果你請(qǐng)求 4 個(gè)數(shù)據(jù)分段(1GB 本機(jī)堆),但是僅分配 1 個(gè)本機(jī)堆分段(256MB),則其他 3 個(gè)數(shù)據(jù)分段將不能用于內(nèi)存映射。</p><p> 如果您希望本機(jī)堆大于 2GB,并且運(yùn)行的是 AIX 5.1 或更高版本,那么您可以使用 AIX 超大內(nèi)存模型。與大內(nèi)存模型類似
14、,可以通過一個(gè)鏈接器選項(xiàng)或在運(yùn)行時(shí)使用 LDR_CNTRL 環(huán)境變量來為編譯時(shí)的可執(zhí)行程序啟用超大內(nèi)存模型。要在運(yùn)行時(shí)啟用超大內(nèi)存模型,需置 LDR_CNTRL=MAXDATA=0xN0000000@DSA。其中, N 位于 0 和 D 之間(如果您使用 AIX 5.2 或更高版本),或于 1 和 A 之間(
15、如果您使用 AIX 5.1)。 N 值指定可用于本機(jī)堆的分段數(shù)量,但與大內(nèi)存模型不同,這些分段可以在必要時(shí)用于映射。</p><p> 通常,IBM Java 運(yùn)行時(shí)使用超大內(nèi)存模型,除非它被 LDR_CNTRL 環(huán)境變量覆蓋。</p><p> 將 N 設(shè)置為 1 和 A 之間,這會(huì)使
16、用 3 和 C 之間的分段作為本機(jī)存儲(chǔ)。在 AIX 5.2 中,將 N 設(shè)置為 B 或更多會(huì)更改內(nèi)存布局 — 它不再使用 D 和 F 作為共享庫(kù),并且允許它們用于本機(jī)存儲(chǔ)或映射。將 N 設(shè)置為 D 可分配最多 13 個(gè)分段(3.25GB)的堆。將 N 設(shè)置為 0 可允許分段 3 到 F 用于映射 — 本機(jī)堆保存在分段
17、2 中。</p><p> 本機(jī)內(nèi)存泄漏或本機(jī)內(nèi)存過度使用會(huì)造成各種問題,這取決于您是耗盡了地址空間還是用完了物理內(nèi)存。耗盡地址空間通常只發(fā)生在 32 位進(jìn)程中 — 因?yàn)榭梢暂p松地分配最大 4GB 地址空間。64 位進(jìn)程的用戶空間可以達(dá)到上千 GB,并且難以用完。如果您確實(shí)耗盡了 Java 進(jìn)程的地址空間,則 Java 運(yùn)行時(shí)會(huì)開始出現(xiàn)一些奇怪的癥狀,本文將在稍后討論這些情況。在進(jìn)程地址空間大于物理內(nèi)存的系統(tǒng)中
18、,內(nèi)存泄漏或本機(jī)內(nèi)存過度使用會(huì)迫使操作系統(tǒng)提供一些虛擬地址空間。訪問操作系統(tǒng)提供的內(nèi)存地址要比讀取(物理內(nèi)存中的)常駐地址慢很多,因?yàn)楸仨氂脖P驅(qū)動(dòng)器加載它。</p><p> 如果您同時(shí)嘗試使用過多 RAM 虛擬內(nèi)存,造成數(shù)據(jù)無法存儲(chǔ)在物理內(nèi)存中,則系統(tǒng)掛起(thrash)— 也就是花費(fèi)大多數(shù)時(shí)間在交換空間與內(nèi)存之間來回復(fù)制數(shù)據(jù)。出現(xiàn)這種情況時(shí),計(jì)算機(jī)和各應(yīng)用程序的性能將變得很差,用戶會(huì)立即覺察到出現(xiàn)了問題。當(dāng)
19、 JVM 的 Java 堆被換出時(shí),垃圾收集器的性能將變得極差,甚至?xí)斐蓱?yīng)用程序掛起。如果多個(gè) Java 運(yùn)行時(shí)在一臺(tái)機(jī)器上同時(shí)運(yùn)行,則物理內(nèi)存必須滿足所有 Java 堆的需要。</p><p> Java 運(yùn)行時(shí)如何使用本機(jī)內(nèi)存</p><p> Java 運(yùn)行時(shí)是一個(gè) OS 進(jìn)程,它受上一節(jié)所提到的硬件及操作系統(tǒng)限制。運(yùn)行時(shí)環(huán)境提供由一些未知用戶代碼驅(qū)動(dòng)的功能;這使得無法預(yù)測(cè)運(yùn)行
20、時(shí)環(huán)境在各種情況下需要哪些資源。Java 應(yīng)用程序在托管 Java 環(huán)境中采取的每一個(gè)措施都有可能影響提供該環(huán)境的運(yùn)行時(shí)的資源需求。本節(jié)討論 Java 應(yīng)用程序消耗本機(jī)內(nèi)存的方式及原因。</p><p> Java 堆和垃圾收集</p><p> Java 堆是分配給對(duì)象的內(nèi)存區(qū)。IBM Developer Kits for Java Standard Edition 擁有一個(gè)物理堆,
21、但一些專門的 Java 運(yùn)行時(shí),比如 IBM WebSphere Real Time,則有多個(gè)堆。堆可以分為多個(gè)部分,例如 IBM gencon 策略的 nursery 和 tenured 區(qū)。大多數(shù) Java 堆都是作為本機(jī)內(nèi)存的相鄰 slab 實(shí)現(xiàn)的。</p><p> 控制堆大小的方法是在 Java 命令行中使用 -Xmx 和 -Xms
22、 選項(xiàng)(mx 是堆的最大大小,ms 是初始大小)。雖然邏輯堆(活躍使用的內(nèi)存區(qū))將根據(jù)堆中對(duì)象的數(shù)量和垃圾收集(CG)所花費(fèi)的時(shí)間增大或縮小,但所使用的本機(jī)內(nèi)存量仍然保持不變,并且將由 -Xmx 值(最大堆大?。Q定。內(nèi)存管理器依賴作為相鄰內(nèi)存 slab 的堆,因此當(dāng)堆需要擴(kuò)展時(shí)無法分配更多本機(jī)內(nèi)存;所有堆內(nèi)存必須預(yù)先保留。</p><p> 保留本機(jī)內(nèi)存與分配
23、它不同。保留本機(jī)內(nèi)存時(shí),它不受物理內(nèi)存或其他存儲(chǔ)的支持。雖然保留地址空間塊不會(huì)耗盡物理資源,但它確實(shí)能防止內(nèi)存用于其他目的。保留從未使用的內(nèi)存造成的泄漏與已分配內(nèi)存的泄漏同樣嚴(yán)重。</p><p> AIX 上的 IBM 垃圾收集器將最大限度減少物理內(nèi)存的使用,當(dāng)使用的堆區(qū)域減少時(shí),它會(huì)釋放堆的備份存儲(chǔ)。</p><p> 對(duì)于大多數(shù) Java 應(yīng)用程序,Java 堆是最大的進(jìn)程地址空
24、間使用者,因此 Java 啟動(dòng)程序使用 Java 堆大小來確定如何配置地址空間。</p><p> 即時(shí)(Just-in-time,JIT)編譯器</p><p> JIT 編譯器在運(yùn)行時(shí)將 Java 字節(jié)碼編譯為優(yōu)化的二進(jìn)制碼。這將極大地改善 Java 運(yùn)行時(shí)的速度,并允許 Java 應(yīng)用程序的運(yùn)行速度能與本機(jī)代碼相提并論。</p><p> 編譯字節(jié)碼將使
25、用本機(jī)內(nèi)存(就像靜態(tài)編譯器一樣,比如 gcc,需要內(nèi)存才能運(yùn)行),但是 JIT 的輸出(可執(zhí)行代碼)也可以存儲(chǔ)在本機(jī)內(nèi)存中。包含許多經(jīng)過 JIT 編譯的方法的 Java 應(yīng)用程序比較小的應(yīng)用程序使用更多本機(jī)內(nèi)存。</p><p><b> 類和類加載器</b></p><p> Java 應(yīng)用程序由定義對(duì)象結(jié)構(gòu)和方法邏輯的類組成。它們還使用 Java 運(yùn)
26、行時(shí)類庫(kù)中的類(比如 java.lang.String),并且可以使用第三方庫(kù)。這些類需要在它們的使用期間存儲(chǔ)在內(nèi)存中。</p><p> Java 5 之后的 IBM 實(shí)現(xiàn)為各類加載器分配本機(jī)內(nèi)存 slab,用于存儲(chǔ)類數(shù)據(jù)。Java 5 中的共享類技術(shù)將共享內(nèi)存中的某個(gè)區(qū)域映射到存儲(chǔ)只讀(因此可以共享)類數(shù)據(jù)的地址空間。當(dāng)多個(gè) JVM 在同一臺(tái)機(jī)器上運(yùn)行時(shí),這將減少存儲(chǔ)類數(shù)據(jù)所需的物理內(nèi)存量。共享類
27、還可以改善 JVM 的啟動(dòng)時(shí)間。</p><p> 共享類系統(tǒng)將固定大小的共享內(nèi)存區(qū)域映射到地址空間??梢圆煌耆加霉蚕眍惥彺?,并且其中還可以包含當(dāng)前未使用的類(由其他 JVM 載入),因此使用共享類將比未使用共享類占用更多地址空間(但物理內(nèi)存較少)。需要重點(diǎn)注意,共享類不能防止類加載器取消加載 — 但它會(huì)造成類數(shù)據(jù)的一個(gè)子集保留在類緩存中。</p><p> 加載更多類需要使用更多本
28、機(jī)內(nèi)存。每個(gè)類加載器還有各自的本機(jī)內(nèi)存開銷 — 因此讓許多類加載分別加載一個(gè)類會(huì)比讓一個(gè)類加載器許多類使用更多本機(jī)內(nèi)存。記住,不僅您的應(yīng)用程序類需要占用內(nèi)存;框架、應(yīng)用服務(wù)器、第三方庫(kù)和 Java 運(yùn)行時(shí)都包含根據(jù)需要加載且占用空間的類。</p><p> Java 運(yùn)行時(shí)可以卸載類以回收空間,但僅限于一些嚴(yán)格的條件下。不能卸載單個(gè)類;而應(yīng)卸載類加載器,其對(duì)象是加載的所有類。卸載類加載器的條件僅限于:</
29、p><p> Java 堆未包含到表示該類加載器的 java.lang.ClassLoader 對(duì)象的引用。</p><p> Java 堆未包含到表示該類加載器加載的類的任何 java.lang.Class 對(duì)象的引用。</p><p> 該類加載器加載的任何類的對(duì)象在 Java 堆中都處于非活動(dòng)狀態(tài)(即未被引用)。<
30、;/p><p> 注意,Java 運(yùn)行時(shí)為所有 Java 應(yīng)用程序創(chuàng)建的 3 個(gè)類默認(rèn)加載器 — bootstrap、extension 和 application — 永遠(yuǎn)都無法滿足這些標(biāo)準(zhǔn);因此,通過應(yīng)用程序類加載器加載的任何系統(tǒng)類(比如 java.lang.String)或任何應(yīng)用程序類都不能被釋放。</p><p> 即使類加載器可
31、用于收集,但運(yùn)行時(shí)只將類加載器作為 GC 周期的一部分進(jìn)行收集。IBM gencon GC 策略(通過 -Xgcpolicy:gencon 命令行參數(shù)啟用)僅卸載主要(tenured)收集上的類加載器。如果某個(gè)應(yīng)用程序正在運(yùn)行 gencon 策略并創(chuàng)建和釋放許多類加載器,則您會(huì)發(fā)現(xiàn)大量本機(jī)內(nèi)存在 tenured 收集期間由可收集的類加載器保存。</p><p> 還可以在運(yùn)行時(shí)生成類,而不需
32、要您釋放它。許多 JEE 應(yīng)用程序使用 JavaServer Pages (JSP) 技術(shù)生成 Web 頁(yè)面。使用 JSP 為執(zhí)行的各個(gè) . jsp 頁(yè)面生成類,該類的持續(xù)時(shí)間為加載它們的類加載器的生存期 — 通常為 Web 應(yīng)用程序的生存期。</p><p> 生成類的另一個(gè)種常用方法是使用 Java 反射。使用 java.lang.reflect API 時(shí),Java 運(yùn)行時(shí)必須將反射對(duì)
33、象的方法(比如 java.lang.reflect.Field)連接到被反射的對(duì)象或類。這種 “訪問方法” 可以使用 Java Native Interface (JNI),它需要的設(shè)置非常少但運(yùn)行緩慢,或者它可以在運(yùn)行時(shí)動(dòng)態(tài)地為您希望反射的各對(duì)象類型構(gòu)建一個(gè)類。后一種方法設(shè)置較慢,但運(yùn)行更快,因此它對(duì)于經(jīng)常反射特定類的應(yīng)用程序非常理想。</p><p> 在最初幾次反射類時(shí),Java 運(yùn)行時(shí)使用 J
34、NI 方法。但是在使用了幾次之后,訪問方法將擴(kuò)展到字節(jié)訪問方法中,該方法涉及構(gòu)建一個(gè)類并通過一個(gè)新的類加載器來加載它。執(zhí)行大量反射會(huì)造成創(chuàng)建許多訪問程序類和類加載器。保留到反射對(duì)象的引用會(huì)造成這些類保持為活動(dòng)狀態(tài)并繼續(xù)占用空間。由于創(chuàng)建字節(jié)碼訪問程序相當(dāng)慢,因此 Java 運(yùn)行時(shí)可以緩存這些訪問程序供稍后使用。一些應(yīng)用程序和框架還緩存反射對(duì)象,因此會(huì)增加它們的本機(jī)內(nèi)存占用。</p><p> 您可以使用系統(tǒng)屬性
35、控制反射訪問程序行為。IBM Developer Kit for Java 5.0 的默認(rèn)擴(kuò)展閥值(JNI 存取器在擴(kuò)展到字節(jié)碼存取器中之前的使用次數(shù))是 15。您可以通過設(shè)置 sun.reflect.inflationThreshold 系統(tǒng)屬性來修改該值。您可以在 Java 命令行中通過 -Dsun.reflect.inflationThreshold=N 來設(shè)置它。如果您將 inf
36、lationThreshold 設(shè)置為 0 或更小的值,則存取器將永遠(yuǎn)不會(huì)擴(kuò)展。如果您發(fā)現(xiàn)應(yīng)用程序要?jiǎng)?chuàng)建許多sun.reflect.DelegatingClassloader(用于加載字節(jié)碼存取器的類加載器),則這種設(shè)置非常有用。</p><p> 另一種(極易造成誤解的)設(shè)置也會(huì)影響反射存取器。-Dsun.reflect.noInflation=true 會(huì)完全禁用擴(kuò)展
37、,但它會(huì)造成字節(jié)碼存取器濫用。使用 -Dsun.reflect.noInflation=true 會(huì)增加反射類加載器占用的地址空間量,因?yàn)闀?huì)創(chuàng)建更多的類加載器。</p><p> 您可以通過 javacore 轉(zhuǎn)儲(chǔ)來測(cè)量類和 JIT 代碼在 Java 5 及以上版本中使用了多少內(nèi)存。javacore 是一個(gè)純文本文件,它包含轉(zhuǎn)儲(chǔ)發(fā)生時(shí) Java 運(yùn)行時(shí)的內(nèi)部狀態(tài)的概述 — 包括關(guān)于已分配本機(jī)
38、內(nèi)存分段的信息。較新版本的 IBM Developer Kit for Java 5 和 6 將內(nèi)存使用情況歸訥在 javacore 中,對(duì)于較老版本(Java 5 SR10 和 Java 6 SR3 之前),本文的示例代碼包包括一個(gè) Perl 腳本,可以用于分配和呈現(xiàn)數(shù)據(jù) 。如果要運(yùn)行它,您需要 Perl 解釋器,它可以用于 AIX 和其他平臺(tái)。</p><p><b> 譯文:</
39、b></p><p> The Java heap</p><p> The heap of Java, where every Java object is allocated, is the area of memory you're most intimately connected with when writing Java applications. The
40、JVM was designed to insulate us from the host machine's peculiarities, so it's natural to think about the heap when you think about memory. You've no doubt encountered a Java heap OutOfMemoryError —
41、 caused by an object leak or by not making the heap big enough to store all your data — and have probably learned a few tricks to debug these scenario</p><p> A Java applications run in the Java virtualized
42、 environment of the Java runtime, but the runtime itself is a native program written in a language (such as C) that consumes native resources, including native memory. Native memory is the memory available to the ru
43、ntime process, as distinguished from the Java heap memory that a Java application uses. Every virtualized resource — including the Java heap and Java threads — must be stored in native memory, along with the data used by
44、 the virtual machi</p><p> This article is one of two covering the same topic on different platforms. In both, you'll learn what native memory is, how the Java runtime uses it, what running out of it lo
45、oks like, and how to debug a native OutOfMemoryError. This article covers AIX and focuses on the IBM® Developer Kit for Java. </p><p> Though Many of the restrictions that a native process experie
46、nces are imposed by the hardware, not the OS. Every computer has a processor and some random-access memory (RAM), also known as physical memory. A processor interprets a stream of data as instructions to execute; it has
47、one or more processing units that perform integer and floating-point arithmetic as well as more advanced computations. A processor has a number of registers — very fast memory elements that are used as working
48、storage f</p><p> The processor is connected to physical memory by the memory bus. The size of the physical address (the address used by the processor to index physical RAM) limits the amount of memory that
49、 can be addressed. For example, a 16-bit physical address can address from 0x0000 to 0xFFFF, which gives 2^16 = 65536 unique memory locations. If each address references a byte of storage, a 16-bit physical address would
50、 allow a processor to address 64KB of memory.</p><p> Processors are described as being a certain number of bits. This normally refers to the size of the registers, although there are exceptions — such as 3
51、90 31-bit — where it refers to the physical address size. For desktop and server platforms, this number is 31, 32, or 64; for embedded devices and microprocessors, it can be as low as 4. The physical address size can be
52、the same as the register width but could be larger or smaller. Most 64-bit processors can run 32-bit programs when running a sui</p><p> Operating systems and virtual memory</p><p> If you wer
53、e writing applications to run directly on the processor without an OS, you could use all memory that the processor can address (assuming enough physical RAM is connected). But to enjoy features such as multitasking and h
54、ardware abstraction, nearly everybody uses an OS of some kind to run their programs.</p><p> In multitasking OSs, including AIX, more than one program uses system resources, including memory. Each program n
55、eeds to be allocated regions of physical memory to work in. It's possible to design an OS such that every program works directly with physical memory and is trusted to use only the memory it has been given. Some embe
56、dded OSs work like this, but it's not practical in an environment consisting of many programs that are not tested together because any program could corrupt the memory of </p><p> Virtual memory al
57、lows multiple processes to share physical memory without being able to corrupt one another's data. In an OS with virtual memory (such as AIX and many others), each program has its own virtual address space — a logica
58、l region of addresses whose size is dictated by the address size on that system (so 31, 32, or 64 bits for desktop and server platforms). Regions in a process's virtual address space can be mapped to physical memory,
59、 to a file, or to any other addressable storage. Th</p><p> Each instance of a native program runs as a process. On AIX a process is a collection of information about OS-controlled resources (such as file a
60、nd socket information), a virtual address space, and at least one thread of execution.</p><p> Although a 32-bit address can reference 4GB of data, a program is not given the entire 4GB address space for it
61、s own use. As with other OS the address space is divided up into sections, only some of which are available for a program to use; the OS uses the rest. Compared to Windows and Linux, the AIX memory model is more complica
62、ted and can be tuned more precisely.</p><p> The AIX 32-bit memory model is divided and managed as 16 256MB segments. Figure 2 shows the layout of the default 32-bit AIX memory model.</p><p>
63、The user program can only directly control 12 out of 16 segments — 3 out of 4GB. The most significant restriction is that the native heap and all thread stacks are held in segment 2. To accommodate programs with larger d
64、ata requirements, AIX provides the large memory model.</p><p> The large memory model allows a programmer or a user to annex some of the shared/mapped segments for use as native heap either by supplyin
65、g a linker option when the executable is built or by setting the LDR_CNTRL environment variable before the program is started. To enable the large memory model at run time, set LDR_CNTRL=MAXDATA=0xN0000000
66、 where N is between 1 and8. Any value outside this range will cause the default memory model to be used. In the large memory model, the native heap starts at</p><p> When you use th
67、e large memory model, the segment allocation is static; that is, if you request four data segments (for 1GB of native heap) but then only allocate one segment (256MB) of native heap, the other three data segments are una
68、vailable for memory mapping.</p><p> If you want a native heap larger than 2GB and you are running AIX 5.1 or later, you can use the AIX very large memory model. The very large memory model, like the l
69、arge memory model, can be enabled for an executable at compile time with a linker option or at run time using the LDR_CNTRL environment variable. To enable the very large memory model at run time, setLDR_CNTRL
70、=MAXDATA=0xN0000000@DSA where N is between 0 and D if you use AIX 5.2 or greater, or between 1 and A if you are using AIX 5.1.</p><p> The IBM Java run
71、time uses the very large memory model unless it's overridden with the LDR_CNTRL environment variable.</p><p> Setting N between 1 and A will use the segments betw
72、een 3 and C for native storage as you would expect. From AIX 5.2, setting Nto B or higher changes the memory layout — it no longer uses segments D and F for shared libraries and allows them to be used for
73、native storage or mmapping. Setting N to D gives the maximum 13 segments (3.25GB) of native heap. Setting N to 0allows segments 3 through F to be used for mmapping — the native heap is
74、held in segment 2.</p><p> A native memory leak or excessive native memory use will cause different problems depending on whether you exhaust the address space or run out of physical memory. Exhausting the
75、address space typically only happens with 32-bit processes — because the maximum 4GB of address space is easy to allocate. A 64-bit process has a user space of hundreds or thousands of gigabytes and is hard to fill up ev
76、en if you try. If you do exhaust the address space of a Java process, then the Java runtime can start</p><p> If you are simultaneously trying to use so much RAM-backed virtual memory that your data cannot
77、be held in physical memory, the system will thrash — that is, spend most of its time copying memory back and forth from swap space. When this happens, the performance of the computer and the individual applications will
78、become so poor the user can't fail to notice there's a problem. When a JVM's Java heap is swapped out, the garbage collector's performance becomes extremely poor, to the extent that th</p><p>
79、; How the Java runtime uses native memory</p><p> The Java runtime is an OS process that is subject to the hardware and OS constraints I outlined in the preceding section. Runtime environments provide capa
80、bilities that are driven by some unknown user code; that makes it impossible to predict which resources the runtime environment will require in every situation. Every action a Java application takes inside the managed Ja
81、va environment can potentially affect the resource requirements of the runtime that provides that environment. This section d</p><p> The Java heap and garbage collection.</p><p> The Java hea
82、p is the area of memory where objects are allocated. The IBM Developer Kits for Java Standard Edition have one physical heap, although some specialist Java runtimes such as IBM WebSphere Real Time have multiple heaps.<
83、;/p><p> The heap can be split up into sections such as the IBM gencon policy's nursery and tenured areas. Most Java heaps are implemented as contiguous slabs of native memory.</p>
84、;<p> The heap's size is controlled from the Java command line using the -Xmx and -Xms options (mx is the maximum size of the heap,ms is the initial size). Although the logical h
85、eap (the area of memory that is actively used) will grow and shrink according to the number of objects on the heap and the amount of time spent in garbage collection (GC), the amount of native memory used remains constan
86、t and is dictated by the -Xmx value: the maximum heap size. The memory manager relies on the heap being a co</p><p> Reserving native memory is not the same as allocating it. When native memory is
87、 reserved, it is not backed with physical memory or other storage. Although reserving chunks of the address space will not exhaust physical resources, it does prevent that memory from being used for other purposes. A lea
88、k caused by reserving memory that is never used is just as serious as leaking allocated memory.</p><p> The IBM garbage collector on AIX minimises the use of physical memory by decommitting (releasing the b
89、acking storage for) sections of the heap as the used area of heap shrinks.</p><p> For most Java applications, the Java heap is the largest user of process address space, so the Java launcher uses the Java
90、heap size to decide how to configure the address space. Table 2 lists the default memory model configuration for different ranges of heap size. You can override the memory model by setting the LDR_CNTRL environ
91、ment variable yourself before starting the Java launcher. If you are embedding the Java runtime or writing your own launcher, you will need to configure the memory mod</p><p> The Just-in- time (JIT) compil
92、er</p><p> The JIT compiler compiles Java bytecode to optimised native binary code at run time. This vastly improves the run-time speed of Java runtimes and allows Java applications to run at speeds compara
93、ble to native code.</p><p> Compiling bytecode uses native memory (in the same way that a static compiler such as gcc requires memory to run), but the output from the JIT (the executable code) als
94、o mist be stored in native memory. Java applications that contain many JIT-compiled methods use more native memory than smaller applications.</p><p> Classes and classloaders</p><p> Java appl
95、ications are composed of classes that define object structure and method logic. They also use classes from the Java runtime class libraries (such as java.lang.String) and may use third-party libraries. These classes
96、 need to be stored in memory for as long as they are being used.</p><p> The IBM implementation from Java 5 onward allocates slabs of native memory for each classloader to store class data in. The shared-cl
97、asses technology in Java 5 and above maps an area of shared memory into the address space where read-only (and therefore shareable) class data is stored. This reduces the amount of physical memory required to store class
98、 data when multiple JVMs run on the same machine. Shared classes also improves JVM start-up time.</p><p> The shared-classes system maps a fixed-size area of shared memory into the address space. The shared
99、 class cache might not be completely occupied or might contain classes that you are not currently using (that have been loaded by other JVMs), so it's quite likely that using shared classes will occupy more address s
100、pace (although less physical memory) than running without shared classes. It's important to note that shared classes doesn't prevent classloaders being unloaded — but it does cause a s</p><p> Loadi
101、ng more classes uses more native memory. Each classloader also has a native-memory overhead — so having many classloaders each loading one class uses more native memory than having one classloader that loads many classes
102、. Remember that it's not only your application classes that need to fit in memory; frameworks, application servers, third-party libraries, and Java runtimes contain classes that are loaded on demand and occupy space.
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫(kù)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 畢業(yè)論文外文翻譯-java和因特網(wǎng)
- 畢業(yè)論文外文翻譯-java的歷史
- java編程思想-畢業(yè)論文外文文獻(xiàn)翻譯
- 法學(xué)畢業(yè)論文相關(guān)外文翻譯
- java相關(guān)外文翻譯
- 畢業(yè)論文——java
- java畢業(yè)論文
- 鍛造畢業(yè)論文外文翻譯
- ,畢業(yè)論文外文翻譯.pdf
- ,畢業(yè)論文外文翻譯.pdf
- 英語(yǔ)畢業(yè)論文外文翻譯
- 車床畢業(yè)論文外文翻譯
- 畢業(yè)論文設(shè)計(jì)外文翻譯
- 畢業(yè)論文外文資料翻譯
- 畢業(yè)論文外文翻譯-車床
- 畢業(yè)論文外文翻譯.doc
- ,畢業(yè)論文外文翻譯.pdf
- 恒流源-畢業(yè)論文外文翻譯
- 換熱器-畢業(yè)論文外文翻譯
- 畢業(yè)論文外文翻譯模板
評(píng)論
0/150
提交評(píng)論