很多使用 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++ 代码 用户的 820.html">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 分区 .