1, 堆内存
Java 中的堆是 JVM 所管理的最大的一块内存空间, 主要用于存放各种类的实例对象.
在 Java 中, 堆被划分成两个不同的区域: 新生代 ( Young ), 老年代 ( Old ). 新生代 ( Young ) 又被划分为三个区域: Eden,From Survivor,To Survivor.
这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象, 包括内存的分配以及回收.
堆的内存模型大致为:
从图中可以看出: 堆大小 = 新生代 + 老年代. 其中, 堆的大小可以通过参数 -Xms,-Xmx 来指定.
默认的, 新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 -XX:NewRatio 来指定 ), 即: 新生代 ( Young ) = 1/3 的堆空间大小. 老年代 ( Old ) = 2/3 的堆空间大小. 其中, 新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域, 这两个 Survivor 区域分别被命名为 from 和 to, 以示区分.
默认的, Eden : from : to = 8 : 1 : 1 ( 可以通过参数 -XX:SurvivorRatio 来设定 ), 即: Eden = 8/10 的新生代空间大小, from = to = 1/10 的新生代空间大小.
JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务, 所以无论什么时候, 总是有一块 Survivor 区域是空闲着的. 因此, 新生代实际可用的内存空间为 9/10 ( 即 90% )的新生代空间.
2,GC 堆
Java 中的堆也是 GC 收集垃圾的主要区域. GC 分为两种: Minor GC,Full GC ( 或称为 Major GC ).
Minor GC 是发生在新生代中的垃圾收集动作, 所采用的是复制算法.
新生代几乎是所有 Java 对象出生的地方, 即 Java 对象申请的内存以及存放都是在这个地方. Java 中的大部分对象通常不需长久存活, 具有朝生夕灭的性质. 当一个对象被判定为 "死亡" 的时候, GC 就有责任来回收掉这部分对象的内存空间. 新生代是 GC 收集垃圾的频繁区域. 当对象在 Eden ( 包括一个 Survivor 区域, 这里假设是 from 区域 ) 出生后, 在经过一次 Minor GC 后, 如果对象还存活, 并且能够被另外一块 Survivor 区域所容纳 ( 上面已经假设为 from 区域, 这里应为 to 区域, 即 to 区域有足够的内存空间来存储 Eden 和 from 区域中存活的对象 ), 则使用复制算法将这些仍然还存活的对象复制到另外一块 Survivor 区域 ( 即 to 区域 ) 中, 然后清理所使用过的 Eden 以及 Survivor 区域 ( 即 from 区域 ), 并且将这些对象的年龄设置为 1, 以后对象在 Survivor 区每熬过一次 Minor GC, 就将对象的年龄 + 1, 当对象的年龄达到某个值时 ( 默认是 15 岁, 可以通过参数 -XX:MaxTenuringThreshold 来设定 ), 这些对象就会成为老年代. 但这也不是一定的, 对于一些较大的对象 ( 即需要分配一块较大的连续内存空间 ) 则是直接进入到老年代. Full GC 是发生在老年代的垃圾收集动作, 所采用的是标记 - 清除算法. 现实的生活中, 老年代的人通常会比新生代的人 "早死". 堆内存中的老年代(Old) 不同于个, 老年代里面的对象几乎个个都是在 Survivor 区域中熬过来的, 它们是不会那么容易就 "死掉" 了的. 因此, Full GC 发生的次数不会有 Minor GC 那么频繁, 并且做一次 Full GC 要比进行一次 Minor GC 的时间更长. 另外, 标记 - 清除算法收集垃圾的时候会产生许多的内存碎片 ( 即不连续的内存空间 ), 此后需要为较大的对象分配内存空间时, 若无法找到足够的连续的内存空间, 就会提前触发一次 GC 的收集动作.
3,GC 日志
设置 JVM 参数为 -XX:+PrintGCDetails, 使得控制台能够显示 GC 相关的日志信息
Full GC 信息与 Minor GC 的信息是相似的. 从 Full GC 信息可知, 新生代可用的内存大小约为 18M, 则新生代实际分配得到的内存空间约为 20M(为什么是 20M? 请继续看下面...). 老年代分得的内存大小约为 42M, 堆的可用内存的大小约为 60M. 可以计算出: 18432K ( 新生代可用空间 ) + 42112K ( 老年代空间 ) = 60544K ( 堆的可用空间 )新生代约占堆大小的 1/3, 老年代约占堆大小的 2/3. 也可以看出, GC 对新生代的回收比较乐观, 而对老年代以及方法区的回收并不明显或者说不及新生代. 并且在这里 Full GC 耗时是 Minor GC 的 22.89 倍.
4,JVM 参数
配置参数 | 功能 |
-Xms | 初始堆大小。如:-Xms256m |
-Xmx | 最大堆大小。如:-Xms512m |
-Xmn | 新生代大小。通常为 Xmx 的 1/3 或 1/4。新生代 = Eden + 2 个 Survivor 空间。实际可用空间为 = Eden + 1 个 Survivor,即 90% |
-Xss | JDK1.5+ 每个线程堆栈大小为 1M,一般来说如果栈不是很深的话, 1M 是绝对够用了的 |
-XX:NewRatio | 新生代与老年代的比例。如 - XX:NewRatio=2,则新生代占堆的 1/3,老年代占 2/3 |
-XX:SurvivorRatio | 新生代中 Eden 与 Survivor 的比值。默认值为 8。即 Eden 占新生代空间的 8/10,另外两个 Survivor 各占 1/10 |
-XX:+PrintGCDetails | 打印 GC 信息 |
-XX:+HeapDumpOnOutOfMemoryError | 让虚拟机在发生内存溢出时 Dump 出当前的内存堆转储快照,以便分析用 |
来源: http://www.bubuko.com/infodetail-3189843.html