`

JVM--内存管理和垃圾回收

    博客分类:
  • jvm
 
阅读更多
一。内存管理
JVM管理两种类型的内存,堆(Heap)和非堆(Non-Heap);
堆是在JVM启动时创建;非堆是留给JVM自己用的,用来存放类的信息的。
它和堆不同,运行期内GC不会释放空间
1)堆
过new创建的对象的内存都在堆中分配,大小通过-Xmx和-Xms来控制。
堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survivor区;
•新生代。新建的对象都是用新生代分配内存,Eden空间不足的时候,
 会把存活的对象转移到Survivor中,新生代大小可以由-Xmn来控制,
 也可以用-XX:SurvivorRatio来控制Eden和Survivor的比例
•旧生代。用于存放新生代中经过多次垃圾回收仍然存活的对象

2)非堆
方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、
每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中

非堆分为永久代(Permanent Generation)及Code Cache
JVM用持久代(Permanet Generation)来存放方法区,,可通过-XX:PermSize和-XX:MaxPermSize来指定最小值和最大值
存放了要加载的类(class)信息、静态变量、final类型的常量、属性和方法信息



二。垃圾回收

垃圾回收的时间分别在:程序线程空闲;另一个是java内存堆不足时

JVM分别对新生代和旧生代采用不同的垃圾回收机制

1)新生代gc
新生代通常存活时间较短,因此基于Copying算法来进行回收,所谓Copying算法就是扫描出存活的对象,
并复制到一块新的完全未使用的空间中,对应于新生代,就是在Eden和From Space或To Space之间copy。
新生代采用空闲指针的方式来控制GC触发,指针保持最后一个分配的对象在新生代区间的位置,当有新的对象要分配内存时,
用于检查空间是否足够,不够就触发GC。当连续分配对象时,对象会逐渐从eden到survivor,最后到旧生代,

2)旧生代gc
旧生代与新生代不同,对象存活的时间比较长,
比较稳定,因此采用标记(Mark)算法来进行回收,
所谓标记就是扫描出存活的对象,然后再进行回收未被标记的对象,
回收后对用空出的空间要么进行合并,要么标记出来便于下次进行分配,
总之就是要减少内存碎片带来的效率损耗

3)为了不影响系统的吞吐量,特别关注Full GC(全局垃圾回收),Full GC一般是由
生代空间不足
调优时尽量让对象在新生代GC时被回收、让对象在新生代多存活一段时间和不要创建过大的对象及数组避免直接在旧生代创建对象 
 •Pemanet Generation空间不足
增大Perm Gen空间,避免太多静态对象 
 •统计得到的GC后晋升到旧生代的平均大小大于旧生代剩余空间
控制好新生代和旧生代的比例 
 •System.gc()被显示调用

内存设置原则:
内存限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),
而64bit以上的处理器就不会有限制了,内存并不是越大越好,如果过大,full gc的时间过长影响系统
这就是为什么系统正常而访问停顿,这个时间在进行垃圾回收。
例子:
JAVA_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=6970 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Xms1400m -Xmx2000m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true -Dfile.encoding=UTF-8" 
注意一下情况:
 1)新生代设置过小
一是新生代GC次数非常频繁,增大系统消耗;二是导致大对象直接进入旧生代,占据了旧生代剩余空间,诱发Full GC
2)新生代设置过大
 
一是新生代设置过大会导致旧生代过小(堆总量一定),从而诱发Full GC;二是新生代GC耗时大幅度增加
 
一般说来新生代占整个堆1/3比较合适
 
3)Survivor设置过小
 
导致对象从eden直接到达旧生代,降低了在新生代的存活时间
 
4)Survivor设置过大
 
导致eden过小,增加了GC频率
附:
   几种常见的错误
   1.java.lang.OutOfMemoryError: PermGen space
   非堆是用来存放类的信息的。它和堆不同,运行期内GC不会释放空间。
   如果web app用了大量的第三方jar或者应用有太多的class文件而恰好MaxPermSize设置较小,
   超出了也会导致这块内存的占用过多造成溢出,或者tomcat热部署时侯不会清理前面加载的环境,
   只会将context更改为新部署的,非堆存的内容就会越来越多。
   2.java.lang.OutOfMemoryError: Javaheap space
   当java内存堆不足时,会不断调用GC,若连续回收都解决不了内存堆不足的问题时,就会报out of memory错误



查看jvm
   C:\Documents and Settings\Administrator>jconsole
   service:jmx:rmi:///jndi/rmi://192.168.150.102:6969/jmxrmi

  • 大小: 1.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics