Java内存区域与OOM http://www.iteye.com/topic/802573
·程序计数器:保留线程执行到的指令
·栈:编译期间预期的变量表。层次深:栈溢出;无法创建更多的栈OOM;线程个数=(系统内存-堆-年老代-保留区域)/每个栈空间
·本地栈:native,也会OOM
·堆(eden、s0、s1+old):生成大量无法回收的对象OOM
·方法区:加载类过多OOM
·常量区:生成太多常量OOM
垃圾收集器与内存分配策略 http://www.iteye.com/topic/802638
·引用计数器:简单,但无法找到循环引用的情况
·搜索算法:从root搜索(比如栈的引用、static方法引用)
·标记-清除:效率低、碎片多
·复制:速度快,浪费内存;适用于90%生出来就要销毁的对象
·ParNew(young)+CMS(old):追求stop-the-world时间更短
full gc触发的可能
·旧生代空间不足:默认68%,CMSInitiatingOccupancyFraction=80
·持久代空间不足:CMSPermGenSweepingEnabled 、CMSClassUnloadingEnabled
·promotion failed:由于救助空间不够,从而向年老代转移对象,年老代没有足够的空间来容纳这些对象,导致一次full gc的产生。解决这个问题的办法有两种完全相反的倾向:增大救助空间、增大年老代或者去掉救助空间。
·concurrent mode failure:问题的产生原因是由于CMS回收年老代的速度太慢,导致年老代在CMS完成前就被沾满,引起full gc,避免这个现象的产生就是调小-XX:CMSInitiatingOccupancyFraction参数的值,让CMS更早更频繁的触发,降低年老代被沾满的可能
·统计得到新生代minor gc时晋升到旧生代的平均大小小于旧生代剩余空间
·直接调用System.gc,可以DisableExplicitGC来禁止
·存在rmi调用时,默认会每分钟执行一次System.gc,可以通过-Dsun.rmi.dgc.server.gcInterval=3600000来设置大点的间隔。
gc小工具
·jps
·jstat :jstat -gcutil/gc/gccause/class -t -h10 pid 1000
·jmap:jmap -heap pid;jmap -histo:live pid;jmap -dump:live,format=b,file=dump.bin pid
·jstack:jstack pid
·jinfo:jinfo -flag xxx pid