程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> IBM i 上 Java Break Memory 介紹與問題分析

IBM i 上 Java Break Memory 介紹與問題分析

編輯:關於JAVA

引言

很多使用 IBM Java 虛擬機的用戶常常有這樣一個疑問:我的程序是應該用 32 位 JVM,還是選擇 64 位 JVM?

我們知道 ,  和 64 位 JVM 相比,32 位 JVM 具有如下優點:

啟動速度快

運行速度快

對同一應用而言,占用的系統資源少

顯而易見 , 32 位 JVM 是用戶的首選。但是 , 采用 32 位尋址 , 32 位 JVM 的可用的內存空間遠比 64 位的小得多 , 所以有些時候用戶不得不使用 64 位 JVM。用戶常會問這樣的問題 : 我的 Java 作業究竟需要多少內存 ?

要回答這一問題,首先要弄清楚 Java 作業的內存結構。Java 應用程序運行時占用的內存包括兩部分:Java Heap 和 Break Memory。 相比較而言,Java Heap 是一個熟悉的術語,它是指對為 Java Object 所准備的空間, 這些 Java Object 會由 JVM 的垃圾回收機制所管理。Break Memory 也是 JVM 內存方面的一個術語 。

本文主要討論 Break Memory,同時介紹 IBM i 上 JVM 的內存分配模型以及如何判斷問題是 Break Memory 上的 OutOfMemory。

什麼是 Break memory

相對 Heap Memory 而言,Break Memory 又叫內部內存或私有內存 .  Break Memory 是在 JVM 中通過 malloc 方式申請的空間 , 具體來說 , 它由如下幾個部分使用 :

Thread Stacks

JVM 的 C/C++ 代碼

用戶的 Native 函數代碼及 Pase 的 Native 函數

為了更好的理解內存結構 , 下面給出了 32bit 內存空間圖表 ( 表 1):

在這個圖表中可以看到 , 程序的內存被分成 16 個分區 , 每個分區是 256M, 這樣一個程序共占用 256*16 = 4G 空間。程序內存的這種布局有如下特性 :

有幾個內存分區是被預先安排為其他用途 , 這幾個分區是不能作為 Java Heap 或 Break Memory 使用的。

Heap Memory 和 Break Memory 使用的空間總額是固定的 , 它們共同占用這些區間 . 在表 1 上 , 從 0x3 到 0xC 是 Break Memory 和 Heap Memory 的空間 . Break Memory 從 0x3 分區開始分配空間 , 而從 0xC 分區按照分區反方向預先保留出來內存空間將留給 Heap Memory 使用 .  Heap Memory 預先保留占用的分區越多 , Break Memory 能使用的分區就越少 , 反之亦然 .

當一個分區其中的任何一部分用做 Heap Memory,則整個分區都將保留下來做這個特定用途使用 , Break Memory 不能再使用這一分區。

在 JVM 啟動的時候 , 可以設定為 Heap Memory 所保留的最大內存空間(-Xmx), 默認是 2GB。

很多時候 , 程序並沒有設定 Heap Memory 大小 . 在這種默認情況下 , 內存的分配布局是 :

Heap Memory 占用 8 個分區 , 2048M. (2048 / 256 = 8)

為運行 JVM 有 6 個內存分區做其它方面的用途 , 包括內核 , 應用程序文本 , 棧數據 , 共享類庫文本 , 等等 .

剩下 2 個內存分區留給 Break Memory: (16 total) - (8 heap) - (6 reserved) = 2

另一種常見的情況是設定 Heap Memory 最大為 1500M, 此時 :

Heap Memory 一共占用 6 個分區 , (1500 / 256 = 5.8)

同上面一樣 , 有 6 個內存分區做其它方面的用途

剩下 4 個分區 (1024 MB) 留給 Break 內存

圖 1. 標准模式

除了上面這種內存結構模式外 , 在一些特別的場景 , JVM 會采用另外兩種內存模式 : 大內存模式及超大內存模式 ( 如下圖 ).

當指定 Heap Memory 最大內存空間(-Xmx)小於或等於 2304M ( 2304/256 = 9 即 9 個分區 ) 時 , 內存模型將采用標准模式 ;

當指定的 Heap Memory 最大內存空間大於 2304M 而小於等於 3072M( 3072/256 = 12 即 12 個分區 ) 時 , 大 Heap Memory 模式將被使用 . 此時 ( 表 2) Heap Memory 占用分區多於 9 個 ( >2304M ). 除了固定占用 0x7 到 0xF 分區外 , Heap Memory 還和 Break Memory 分享從 0x3 到 0x6 的分區 .

當指定的 Heap Memory 最大內存空間大於 3072M 時 , Heap Memory 獨占從 0x3 到 0xF 的 13 個分區的空間 , 此時 Heap Memory 已經達到 32 位 JVM 的內存上限 , 即 3328M.  Break Memory 和主線程棧共同時用 0x2 分區 .

關於大 Heap Memory 模式和超大 Heap Memory 模式 , 這裡不再進一步詳細闡述 .

圖 2. 大 Heap Memory 模式

查看本欄目

圖 3. 超大 Heap Memory 模式

程序需要多少 Break Memory

由於線程堆棧是在 Break 內存中創建的 , 我們在估計所需要的 Break 內存時候 , 可以按照能安全運行多少線程所需的來計算所需的空間大小 . 按照每個線程需要占用 260K 內存計算 , 根據設定的最大的 Heap 大小 , 大致有如下對應關系 :

如何查看 Break Memory 使用情況

查看 Break 內存使用情況可以通過如下兩種方式 :

JVMINFO -memory <taskid> option

在 V5R4 上 , 若想查看 Break 內存的大小 , 可以使用 STRSST 中的 Advanced Analysis 工具 , 通過使用 JVMINFO -memory <taskid> 選項來查看 Break 內存 . 如下圖 , 在 JVMINFO 結果中翻頁找到相應的 Break Memory 部分 .

圖 4. JVMINFO 輸出

WRKJVMJOB

在 V6R1 上 , 除了使用 JVMINFO 外 , 還可以在 WRKJVMJOB 命令中使用"Display Garbage Collection Information"選項得知 Break Memory 的大小 .

圖 5. WRKJVMJOB 輸出

當 Break Memory 不夠時

Break Memory 不足時 , 會有多種不同的表現形式 . 有時候程序內存被破壞 , 有時候出現 core dump(segmentation fault), 有時候完全沒法預測 . 在 V6R1 及以上版本上 , 當 Break 內存中申請空間時候 , JVM 會做是否成功申請空間的判斷 . 如果空間申請空間不成功 , JVM 會拋出 OutOfMemory 異常 . 在 V5R4 上 , 由於底層的系統並不支持這種內存申請檢查機制 , JVM 也就不會象在 V6R1 上那樣拋出 OutOfMemory 異常 . V5R4 上 Break Memory 不足的一個典型表現形式是 JVM Crash.

在 V6R1 上 , 通常有 2 種線索表征 Break Memory 不足或者不夠 :

在主代碼 (Major Code) 為 0200 的 vlog 中 , 某個函數調用棧出現 "<SYSCALL64>:AS_SETH" 字樣 .  "as_seth"是用來映射內存的內核函數

java/lang/OutOfMemory, 出現如下錯誤提示 , "unable to fork native thread"

解決 Break Memory 不夠這類問題 , 需要先判斷問題究竟是因為 Break Memory 出現內存洩露 , 還是單純的 Break Memory 空間不夠 . 首先可通過修改 -Xmx 參數 ( 可適當減小該參數數值 ) 來減少允許 Heap Memory 可用的最大空間 , 這樣 Break Memory 的可用空間將會加大 . 然後在一段合理的時間范圍內觀察 Break Memory 的使用情況。 如果看到 Break Memory 使用量在不斷增加 , 則很可能 Break Memory 中存在內存洩露問題 . 相反如果達到一定數值後 Break Memory 變得平穩不再增加 , 則基本上表明 Break Memory 沒有洩露 , 那麼原來的問題通過增加 Break Memory 即可得到解決 .

上面說的方法 , 可以進行一個初步判定 . 若想要准確定位問題 , 很可能需要檢查相關的代碼 . 為方便檢查代碼 , 可通過設定如下的 Java Option 來輸出所有調用 malloc 之處 :  MALLOCDEBUG=report_allocations

還有一種情況 , 當通過減少 Heap Memory 設定的最大內存空間來增加 Break Memory 空間後 , 又發現 Heap Memory 不夠時 , 這時表明 32 位的內存已經不夠用了 , 我們只能通過使用 64 位 JVM 來解決這一矛盾 .

結束語

本文首先簡單介紹了 IBM i 上 Java job 的內存基本概念,接著 Break Memory 分布結構和相關使用問題 . 在此基礎上介紹如何鑒定是 Break Memory 不夠的問題 , 並給出了解決此類問題的途徑

。Java Memory 是非常復雜的話題。本文只是簡單介紹了其中最基礎的一小部分,要想做到精通這方面的知識,還需要更進一步深入的學習和研究。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved