JVM内存管理机制

堆(Heap)和非堆(Non-heap)内存 按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内 存均从此处分配。堆是在 Java 虚拟机启动时创建的。”“在 JVM 中堆之外的内存称为非堆 内存(Non-heap memory)”。可以看出 JVM 主要管理两种类型的内存:堆和非堆。简单来说 堆就是 Java 代码可及的内存,是留给开发人员使用的;非堆就是 JVM 留给 自己用的,所 以方法区、JVM 内部处理或优化所需的内存(如 JIT 编译后的代码缓存)、每个类结构(如运 行时常数池、字段和方法数据)以及方法和构造方法 的代码都在非堆内存中。 堆内存分配 JVM 初始分配的内存由-Xms 指定, 默认是物理内存的 1/64; JVM 最大分配的内存由 -Xmx 指定,默认是物理内存的 1/4。默认空余堆内存小于 40%时,JVM 就会增大堆直到-Xmx 的 最大限制;空余堆内存大于 70%时,JVM 会减少堆 直到-Xms 的最小限制。因此服务器一 般设置-Xms、-Xmx 相等以避免在每次 GC 后调整堆的大小。 非堆内存分配 JVM 使 用 -XX:PermSize 设 置 非 堆 内 存 初 始 值 , 默 认 是 物 理 内 存 的 1/64 ; 由 XX:MaxPermSize 设置最大非堆内存的大小,默认是物理内存的 1/4。 JVM 内存限制(最大值) 首先 JVM 内存限制于实际的最大物理内存(废话!呵呵),假设物理内存无限 大的话,JVM 内存的最大值跟操作系统有很大的关系。 简单的说就 32 位处理器虽然可控内存空间有 4GB, 但是具体的操作系统会给一个限制,这个限制一般是 2GB-3GB(一般来说 Windows 系统 下为 1.5G-2G,Linux 系统下为 2G-3G) ,而 64bit 以上的处理器就不会有限制了。 众所周知,jvm 的内存是受限的,一为机器的体系架构,二为操作系统本身。 x86,x86-64,SPARC,.....的内存映射是不同,而各操作系统的内存管理机制也有区别。 1. Heap 设定与垃圾回收 Java Heap 分为 3 个区,Young,Old 和 Permanent。Young 保 存刚实例化的对象。当该区被填满时,GC 会将对象移到 Old 区。Permanent 区则负责保存 反射对象,本文不讨论该区。JVM 的 Heap 分配可以使用-X 参数设定, -Xms -Xmx -Xmn 初始 Heap 大小 java heap 最大值 young generation 的 heap 大小 JVM 有 2 个 GC 线程。第一个线程负责回收 Heap 的 Young 区。第二个线程在 Heap 不足 时,遍历 Heap,将 Young 区升级为 Older 区。Older 区的大小等于-Xmx 减去-Xmn,不能 将-Xms 的值设的过大,因为第二个线程被迫运行会降低 JVM 的性能。 为什么一些程序频繁发生 GC?有如下原因: l l l l 程序内调用了 System.gc()或 Runtime.gc()。 一些中间件软件调用自己的 GC 方法,此时需要设置参数禁止这些 GC。 Java 的 Heap 太小,一般默认的 Heap 值都很小。 频繁实例化对象,Release 对象。此时尽量保存并重用对象,例如使用 StringBuffer() 和 String()。 如果你发现每次 GC 后,Heap 的剩余空间会是总空间的 50%,这表示你的 Heap 处 于健康状态。 许多 Server 端的 Java 程序每次 GC 后最好能有 65%的剩余空间。 经验之谈: 1.Server 端 JVM 最好将-Xms 和-Xmx 设为相同值。为了优化 GC,最好让-Xmn 值约等于 -Xmx 的 1/3[2]。 2.一个 GUI 程序最好是每 10 到 20 秒间运行一次 GC,每次在半秒之内完成[2]。 注意: 1.增加 Heap 的大小虽然会降低 GC 的频率,但也增加了每次 GC 的时间。并且 GC 运行 时,所有的用户线程将暂停,也就是 GC 期间,Java 应用程序不做任何工作。 2.Heap 大小并不决定进程的内存使用量。进程的内存使用量要大于-Xmx 定义的值,因为 Java 为其他任务分配内存,例如每个线程的 Stack 等。 2.Stack 的设定 每个线程都有他自己的 Stack。 -Xss 每个线程的 Stack 大小 Stack 的大小限制着线程的数量。如果 Stack 过大就好导致内存溢漏。-Xss 参数决定 Stack 大小,例如-Xss1024K。如果 Stack 太小,也会导致 Stack 溢漏。 3.硬件环境 硬件环境也影响 GC 的效率,例如机器的种类,内存,swap 空间,和 CPU 的数量。 如果你的程序需要频繁创建很多 transient 对象,会导致 JVM 频繁 GC。这种情况你可以增 加机器的内存,来减少 Swap 空间的使用[2]。 4.4 种 GC 第一种为单线程 GC,也是默认的 GC。,该 GC 适用于单 CPU 机器。 第二种为 Throughput GC,是多线程的 GC,适用于多 CPU,使用大量线程的程序。第二 种 GC 与第一种 GC 相似,不同在于 GC 在收集 Young 区是多线程的,但在 Old 区和第一 种一样,仍然采用单线程。-XX:+UseParallelGC 参数启动该 GC。 第三种为 Concurrent Low Pause GC,类似于第一种,适用于多 CPU,并要求缩短因 GC 造成程序停滞的时间。这种 GC 可以在 Old 区的回收同时,运行应用程序。 -XX:+UseConcMarkSweepGC 参数启动该 GC。 第四种为 Incremental Low Pause GC,适用于要求缩短因 GC 造成程序停滞的时间。这种 GC 可以在 Young 区回收的同时,回收一部分 Old 区对象。-Xincgc 参数启动该 GC。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值