1、内存分配与设置
堆内存分配
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。
由Permanent Generation和Code Cache组成
Permanent Generation保存虚拟机自己的静态(refective)数据
主要存放加载的Class类级别静态对象如class本身,method,field等等,permanent generation空间不足会引发full GC
Code Cache 用于编译和保存本地代码(native code)的内存
JVM内部处理或优化 JVM内存限制(最大值)
JVM内存的最大值跟操作系统有很大的关系。简单的说就32位处理器虽然 可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统 下为2G-3G),而64bit以上的处理器就不会有限制了。
内存分布具体说明:
堆中new对象首先进入Eden区,当Eden区满了之后,会触发Young GC 判断Eden区中的对象是否还有指向其的引用,如果没有则被直接回收,如果还有引用指向则将其移入survivor1区;之后当Eden区再次满了时会触发第二次Young GC 判断Eden区中的对象是否还有指向其的引用,如果没有则被直接回收,如果还有引用指向则将其移入survivor2区,同时会判断survivor1区中对象是否还有指向其的引用,如果没有直接回收除,有将其移至survivor2区(第二次Young GC 的时候相当于回收说有无引用的对象同时 s1与s2位置互换);Young GC 循环奖Eden区的对象存入survivor区,而每执行一次age+1,JVM 默认age=15,当age=15之后出发Young GC时将其移入老年代,老年代不断的被移入数据,当老年区满了的时候 触发 full GC ,full GC将对整个堆进行GC,没有引用直接回收,有引用则移入持久代(1.8及以后没有永久代用元空间替代),full GC 不影响Young GC 也不影响对象age
2、内存申请过程
内存申请步骤:
JVM会试图为相关Java对象在Eden区初始化一块内存区域
Eden满足则划分内存,申请结束
Eden不满足则JVM试图释放在Eden区中所有的不活跃对象(YGC),释放后若Eden区空间仍然不足以放入新对象,则试图将部分Eden区中活跃的对象放入Survivor区(YGC)
Survivor区被用来作为Eden区及Old的中间交换区,当Survivor区空间足够时,Survivor区的部分对象(存活次数超过turning threshold)会被移到OLD区,否则会保留在Survivor区
当old区空间不够时,JVM会在old区进行(FGC)
完全垃圾收集后,若Survivor及old区仍然无法存放Eden复制过来的对象,导致JVM无法在Eden区为新对象创建内存区域,则出现 “Out of memory错误”
3、对象衰老过程
大部分新创建的对象的内存都分配自eden区。Minor collection 的过程就是将eden和在survivor space 中的活对象复制到空闲的 survivor space中。对象在 young generation里立即鞥了一定次数的minor collection后就会被移到 old generation中 称为tenuring
4、GC触发条件
YGC
触发条件:eden区空间不足
触发过程:清空年轻代中所有不被引用的对象,将enden和s1中的所有活对象复制到s2中。一些对象将复制到old区(s2中放不下的;存活次数超过turning threshold中的;重新计算tenuring threshold(serial parallel GC会触发此项);重新调整Eden 和from的大小(parallel GC会触发此项);)
注意:全过程暂停应用是否为多线程处理有具体的GC决定
查看方式:jstat –gcutil gc log
Full GC
触发条件:old区空间不足 perm空间不足 显示调用System.GC、RMI等待定时触发YGC时的悲观策略dump live 的内存信息(map -dump:live)时
触发过程:清空heap中不引用的对像permgen区中已经被卸载的class loader中加载的class信息。 如配置了 collectGenORirst则先触发YGC(针对serial GC)
注意:全过程暂停应用 是否为多线程处理取决于具体的GC决定
查看方式:jstat -gcutil gc log
非堆内存默认不GC 可以设置GC这个要看使用的垃圾收集器 CMS策略可以对PermGen进行GC 设置参数是 -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled 1.6之前还要加入-XX:+CMSPermGenSweepingEnabled
堆内存GC
JVM(采用分代算法),用较高的频率对年轻的对象(young generation)采用复制算法进行YGC,而对老对象(tenured generation)较少(tenured generation 满了后才进行)回收,采用标记整理算法进行Full GC。这样就不需要每次GC都将内存中所有对象都检查一遍。
非堆内存不GC
GC不会在主程序运行期对PermGen Space进行清理,所以如果你的应用中有很多CLASS(特别是动态生成类,当然permgen space存放的内容不仅限于类)的话,就很可能出现PermGen Space错误。
总结:
New 对象优先在Eden区
大对象直接进入老年代 有参数设置,超出这个大小进入老年区
长期存活的对象直接进入老年代 默认设置: age=15
class,变量等信息JVM直接加载进入持久代(1.8及以后没有永久代用元空间替代)
老年代和持久代(1.8及以后没有永久代用元空间替代)都会触发full GC
Young GC 只会发生在Eden区
Full gc 时占用时间较长,而在触发GC的时候,会暂停所有线程而full gc的时间较长,所以full gc 的核心思想:
1) 尽可能减少full gc 的次数
2) 尽可能的延长 full gc 的间隔时间
堆内存分布:3/8 堆内存=young
5/8 堆内存=old
young=1:1:8(S1:S2:eden)
GC 作用:1.分配内存 2.确保被引用的对象不被回收 3.回收不可达对像