zoukankan      html  css  js  c++  java
  • Java内存回收(垃圾回收)机制总结

    一、背景:

    Java程序员编写程序时,对于新建的对象,当不再需要此对象时,不必去释放这个对象所占用的空间,这个工作是由Java虚拟机自己完成的 ,即内存回收或垃圾回收。

    二、如何知道一个对象所占用的空间可以回收了呢?

    1.常用的一种算法是引用计数法,如果一个对象的引用为0了,那就可以回收了。但是对于这种方法致命缺陷,当对象之间存在循环引用的时候,A引用B,B引用A,这样A和B的引用就一直不会为0,那就无法回收了。

    2、Java采用的算法为根搜索算法,以一系列GC Roots为起点,向下搜索,如果存在引用,则对象依然在用,不能回收;如果不存在引用,则可以回收。

    可以作为GC Roots的有如下几种:

    a、虚拟机栈(栈帧中的本地变量表)中的引用的对象
    b、方法区中的类静态属性引用的对象
    c、方法区中的常量引用的对象
    d、本地方法栈中JNI的引用的对象

    三、java堆栈内存结构划分:

    1.新生代(Young Generation):又细分为三块(eden,S0,S1)

     新的对象总是在新生代创建。

    2.老年代(Old Generation)

     在新生代存放一定时间之后,在新生代空间不够时,对象会被移到老年代。

    3.永久代(Permanent)

    用于存在类信息。对于动态生成的类,后续不会再使用到,所以可以进行回收。

    四、为什么采用分代(区)的方式来进行堆栈空间的管理呢?

    因为不同的对象存活时间不同,多数对象存活时间很短,少数对象存活时间很长。如果每次回收都遍历所有对象,效率将会非常低。按对象存活时间长短,划分不同的内存区域来管理对象,对不同的区采用不同的回收算法。

    五、主要的空间回收算法:

    1.复制算法

    对于新生代,划分了eden/S0/S1三块区域,开始对象创建在eden区域上。

    下面来描述一下可能的操作过程,各个java虚拟机的实现会有差异,下面是大致进行阐述。

    第一次清理的时候,将可以清除的对象删除,将要保留的对象都复制到S0区域,eden区域清空,对象年龄标记增长1;

    第二次清理的时候,将可以清除的对象删除,将要保留的对象从eden和S0都复制到S1,并将eden和S0都清空,对象年龄标记增长1;

    第三次清理的时候,将可以清除的对象删除,将要保留的对象从eden和S1都复制到S0,并将eden和S1都清空,对象年龄标记增长1;

    后续清理的时候,以此重复上面的步骤,当对象的年龄达到一定值时,就被移到老年代中去。

    对于上面的过程,可以通过jvisualvm观测到,会发现eden和S0同时被清空,对象转移到S1,或eden和S1同时被清空,对象转移到S0.

    下面给出两张jvisualvm的截图:

    时刻1:

    时刻2:

    时刻3:

    通过上面三张图对比可以看到,当S0被占用时,S1就是空的;S1被占用时,S0就是空的,这也就印证了上面算法描述里说的信息。

    2.标记清除算法(包括整理)

    因为老年代中,可以回收的对象很少,所以触发对老年代的回收几率也比较低,对于老年代也不采用复制算法,因为那样空间利用率比较低,而是采用标记清除(整理)方式。如果对应对象的空间可以回收了,就进行回收,并对对象存储位置进行移动,将对象移到到一起,避免中间存在空隙,便于后续内存分配。

    六、几个可以用于指定java虚拟机各个块大小的参数:

    -XX:PermSize       设置永久代初始大小(样例:-XX:PermSize=40M)
    -XX:MaxPermSize    设置永久代最大大小(样例:-XX:MaxPermSize=100M)
    (注:java对此参数值限制,具体限制可能因操作系统、CPU/内存差异而又不同,在Window7上测试时,最小值为12M;不能设置为奇数,必须为偶数)

    -XX:NewSize        设置新生代初始大小(样例:-XX:NewSize=10M)
    -XX:MaxNewSize     设置新生代最大值(样例:-XX:MaxNewSize=20M)
    -XX:SurvivorRatio  设置新生代中eden和survivor区(S0/S1)的比例,通过验证,实际大小比例为该值*1.2,如设置为8,则eden空间大小/S0=8*1.2(样例:-XX:SurvivorRatio=8)
    -Xmx               设置堆栈最大值,包括老年代和新生代,不包括永久代(样例-Xmx100M)
    -Xms               设置堆栈初始大小(样例:-Xms50M)
    -XX:NewRatio       老年代和新生代的大小比例,设置此参数时不能设置MaxNewSize,否则此参数失效(样例:-XX:NewRatio=2)


    参考资料:

    http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

    http://www.open-open.com/lib/view/open1380593930103.html

    http://blog.csdn.net/time_hunter/article/details/12405127

    
    
  • 相关阅读:
    深入Eureka/Feign/Hystrix原理学习(1)
    mysql截取函数substring_index()和right()用法
    Mybatis映射文件的自动映射与手动映射问题
    MySQL单向加密函数
    Grovvy带参数的闭包
    微信小程序开发编程手记20190303
    IDEA 各版本在线激活(激活码)
    Vue实例:演示input 和 textarea 元素中使用 v-model 实现双向数据绑定
    mybatis异常解决:class path resource [SqlMapConfig.xml] cannot be opened because it does not exist
    【学亮IT手记】MySql行列转换案例
  • 原文地址:https://www.cnblogs.com/jerry1999/p/4175926.html
Copyright © 2011-2022 走看看