• 深入理解java虚拟机---内存分配策略(十三)


    转载请注明原文地址:https://blog.csdn.net/initphp/article/details/30487407

    Java内存分配策略

    使用的ParNew+Serial Old收集器组合

    1. 优先在Eden上分配。

    Java的对象优先会在新生代的Eden上分配。

    我们可以看一个例子:

    我设置了这些参数:-XX:+PrintGCDetails -Xms20m -Xmx20m -Xmn10m,堆内存分配20M,新生代10M,老生代10M,默认情况下Survivor区为8:1,所以Eden区域为8M

    我运行这段代码:

    [java] view plain copy
     
    1. public class JavaTest {  
    2.   
    3.     static int m = 1024 * 1024;  
    4.   
    5.     public static void main(String[] args) {  
    6.         //分配2兆  
    7.         byte[] a1 = new byte[2 * m];  
    8.         System.out.println("a1 ok");  
    9.         //分配2兆  
    10.         byte[] a2 = new byte[2 * m];  
    11.         System.out.println("a2 ok");  
    12.     }  
    13. }  


    控制台日志:

    [html] view plain copy
     
    1. a1 ok  
    2. a2 ok  
    3. Heap  
    4.  def new generation   total 9216K, used 4603K [0x331d0000, 0x33bd0000, 0x33bd0000)  
    5.   eden space 8192K,  56% used [0x331d0000, 0x3364ef50, 0x339d0000)  
    6.   from space 1024K,   0% used [0x339d0000, 0x339d0000, 0x33ad0000)  
    7.   to   space 1024K,   0% used [0x33ad0000, 0x33ad0000, 0x33bd0000)  
    8.  tenured generation   total 10240K, used 0K [0x33bd0000, 0x345d0000, 0x345d0000)  
    9.    the space 10240K,   0% used [0x33bd0000, 0x33bd0000, 0x33bd0200, 0x345d0000)  
    10.  compacting perm gen  total 12288K, used 381K [0x345d0000, 0x351d0000, 0x385d0000)  
    11.    the space 12288K,   3% used [0x345d0000, 0x3462f4d0, 0x3462f600, 0x351d0000)  
    12.     ro space 10240K,  55% used [0x385d0000, 0x38b51140, 0x38b51200, 0x38fd0000)  
    13.     rw space 12288K,  55% used [0x38fd0000, 0x396744c8, 0x39674600, 0x39bd0000)  

    日志中非常清晰的可以看到,我们分配了一个4M内存大小,直接是分配在了eden space里面。

    2. 大对象直接进入老生代。

     因为大对象一般是数组或者字符串,我们知道垃圾回收的算法是复制算法,所以需要大对象需要比较多的空间存储对象.在eden区间执行gc频率很高时会耗费很多性能,所以直接将大对象放入到老生代.

    参数:-XX:PretenureSizeThreshold(该设置只对Serial和ParNew收集器生效) 可以设置进入老生代的大小限制,我们设置为3M,则大于3M的大对象就直接进入老生代

    测试代码:

    [java] view plain copy
     
    1. public class JavaTest {  
    2.   
    3.     static int m = 1024 * 1024;  
    4.   
    5.     public static void main(String[] args) {  
    6.         //分配2兆  
    7.         byte[] a1 = new byte[2 * m];  
    8.         System.out.println("a1 ok");  
    9.         byte[] a3 = new byte[4 * m];  
    10.         System.out.println("a2 ok");  
    11.     }  
    12. }  


    控制台日志:

    [html] view plain copy
     
    1. a1 ok  
    2. a2 ok  
    3. Heap  
    4.  def new generation   total 9216K, used 2555K [0x331d0000, 0x33bd0000, 0x33bd0000)  
    5.   eden space 8192K,  31% used [0x331d0000, 0x3344ef40, 0x339d0000)  
    6.   from space 1024K,   0% used [0x339d0000, 0x339d0000, 0x33ad0000)  
    7.   to   space 1024K,   0% used [0x33ad0000, 0x33ad0000, 0x33bd0000)  
    8.  tenured generation   total 10240K, used 4096K [0x33bd0000, 0x345d0000, 0x345d0000)  
    9.    the space 10240K,  40% used [0x33bd0000, 0x33fd0010, 0x33fd0200, 0x345d0000)  
    10.  compacting perm gen  total 12288K, used 381K [0x345d0000, 0x351d0000, 0x385d0000)  
    11.    the space 12288K,   3% used [0x345d0000, 0x3462f4d0, 0x3462f600, 0x351d0000)  
    12.     ro space 10240K,  55% used [0x385d0000, 0x38b51140, 0x38b51200, 0x38fd0000)  
    13.     rw space 12288K,  55% used [0x38fd0000, 0x396744c8, 0x39674600, 0x39bd0000)  


    上面的日志中,可以清洗看到第一次分配的2M留存在了eden space中,而4M超过了大对象设置的值3M,所以直接进入了老生代tenured generation

    3. 长期存活的对象进入老年代

    为了演示方便,我们设置-XX:MaxTenuringThreshold=1(默认15),当在新生代中年龄为1的对象进入老年代。

    测试代码:

    [java] view plain copy
     
    1. public class JavaTest {  
    2.   
    3.     static int m = 1024 * 1024;  
    4.   
    5.     public static void main(String[] args) {  
    6.         //分配2兆  
    7.         byte[] a1 = new byte[1 * m / 4];  
    8.         System.out.println("a1 ok");  
    9.         byte[] a2 = new byte[7 * m];  
    10.         System.out.println("a2 ok");  
    11.         byte[] a3 = new byte[3 * m]; //GC  
    12.         System.out.println("a3 ok");  
    13.     }  
    14. }  


    控制台日志:

    [html] view plain copy
     
    1. a1 ok  
    2. a2 ok  
    3. [GC [DefNew: 7767K->403K(9216K), 0.0062209 secs] 7767K->7571K(19456K), 0.0062482 secs]   
    4. [Times: user=0.00 sys=0.00, real=0.01 secs]   
    5. a3 ok  
    6. Heap  
    7.  def new generation   total 9216K, used 3639K [0x331d0000, 0x33bd0000, 0x33bd0000)  
    8.   eden space 8192K,  39% used [0x331d0000, 0x334f9040, 0x339d0000)  
    9.   from space 1024K,  39% used [0x33ad0000, 0x33b34de8, 0x33bd0000)  
    10.   to   space 1024K,   0% used [0x339d0000, 0x339d0000, 0x33ad0000)  
    11.  tenured generation   total 10240K, used 7168K [0x33bd0000, 0x345d0000, 0x345d0000)  
    12.    the space 10240K,  70% used [0x33bd0000, 0x342d0010, 0x342d0200, 0x345d0000)  
    13.  compacting perm gen  total 12288K, used 381K [0x345d0000, 0x351d0000, 0x385d0000)  
    14.    the space 12288K,   3% used [0x345d0000, 0x3462f548, 0x3462f600, 0x351d0000)  
    15.     ro space 10240K,  55% used [0x385d0000, 0x38b51140, 0x38b51200, 0x38fd0000)  
    16.     rw space 12288K,  55% used [0x38fd0000, 0x396744c8, 0x39674600, 0x39bd0000)  


    我们可以看到在A3处有一次GC,并且a2的7M已经满足-XX:MaxTenuringThreshold=1的要求,所以a2进入老年代,而空出来的空间a3就进入新生代

    4. 动态对象年龄判定

    为了使内存分配更加灵活,虚拟机并不要求对象年龄达到MaxTenuringThreshold才晋升老年代

    如果Survivor区中相同年龄所有对象大小的总和大于Survivor区空间的一半,年龄大于或等于该年龄的对象在Minor GC时将复制至老年代

    5. 空间分配担保

    新生代使用复制算法,当Minor GC时如果存活对象过多,无法完全放入Survivor区,就会向老年代借用内存存放对象,以完成Minor GC。

    在触发Minor GC时,虚拟机会先检测之前GC时租借的老年代内存的平均大小是否大于老年代的剩余内存,如果大于,则将Minor GC变为一次Full GC,如果小于,则查看虚拟机是否允许担保失败,如果允许担保失败,则只执行一次Minor GC,否则也要将Minor GC变为一次Full GC。

    说白了,新生代放不下就会借用老年代的空间来进行GC

  • 相关阅读:
    python while循环语句
    Python if条件语句
    推荐一款java的验证码组件——kaptcha
    Linux硬链接和符号链接(转)
    推荐一款好用的java反编译软件——JavaDecompiler
    数据库性能优化之冗余字段的作用
    通过设置代理,解决服务器禁止抓取,报“java.io.IOException: Server returned HTTP response code: 403 for URL”错误的方法
    浏览器在同域名下有并发加载的限制
    XCODE快捷键和功能汇总篇(不断更新)
    队列应用场景,自己实现队列
  • 原文地址:https://www.cnblogs.com/zhulibin2012/p/8994070.html
Copyright © 2020-2023  润新知