• JVM内存模型以及垃圾回收


    JAVA堆的描述如下:

     

       内存由Perm和Heap组成。其中Heap = {Old + NEW = { Eden , from, to } }

      JVM内存模型中分两大块:

      NEW Generation:程序新创建的对象都是从新生代分配内存,新生代由Eden Space和两块相同大小的Survivor Space(通常又称S0和S1或From和To)构成,可通过-Xmn参数来指定新生代的大小,也可以通过-XX:SurvivorRation来调整Eden Space及Survivor Space的大小。垃圾回收一般用Copying的算法,速度快。每次GC的时候,存活下来的对象首先由Eden拷贝到某个Survivor Space, 当Survivor Space空间满了后, 剩下的live对象就被直接拷贝到Old Generation中去。因此,每次GC后,Eden内存块会被清空

      Old Generation:用于存放经过多次新生代GC任然存活的对象和应用程序中生命周期长的内存对象,例如缓存对象,新建的对象也有可能直接进入老年代,主要有两种情况:①大对象,可通过启动参数设置-XX:PretenureSizeThreshold=1024(单位为字节,默认为0)来代表超过多大时就不在新生代分配,而是直接在老年代分配。②大的数组对象,切数组中无引用外部对象。老年代所占的内存大小为-Xmx对应的值减去-Xmn对应的值。在Old Generation块中,垃圾回收一般用mark-compact的算法,速度慢些,但减少内存要求。

      PS:还有个Permanent Generation,主要用来放JVM自己的反射对象,比如类对象和方法对象等。

       

      垃圾回收描述:

      现在收集器都是采用分代收集算法,堆被划分为新生代和老年代。新生代主要存储新创建的对象和尚未进入老年代的对象。老年代存储经过多次新生代GC(Minor GC)任然存活的对象。

      Minor GC:即新生代GC,指发生在新生代的垃圾收集动作,因为Java对象大多都具备朝生夕灭的特性,所以Minor GC非常频繁,一般回收速度也比较快。垃圾回收分多级是1级或以上为部分垃圾回收,只会回收NEW中的垃圾。

      Major GC  / Full GC:老年代GC,指发生在老年代的GC,出现了Major GC,经常会伴随至少一次的Minor GC(但非绝对的,在 ParallelScavenge 收集器的收集策略里就有直接进行 Major GC的策略选择过程) 。MajorGC 的速度一般会比Minor GC慢10倍以上。垃圾回收分多级是0级为全部(Full)的垃圾回收,会回收OLD段中的垃圾。

      PS:内存溢出通常发生于OLD段或Perm段垃圾回收后,Eden区仍然无内存空间容纳新的Java对象的情况。

      当一个URL被访问时,内存申请过程如下:

      A. JVM会试图为相关Java对象在Eden中初始化一块内存区域

      B. 当Eden空间足够时,内存申请结束。否则到下一步

      C. JVM试图释放在Eden中所有不活跃的对象(这属于1或更高级的垃圾回收), 释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区

      D. Survivor区被用来作为Eden及OLD的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区

      E. 当OLD区空间不够时,JVM会在OLD区进行完全的垃圾收集(0级

      F. 完全垃圾收集后,若Survivor及OLD区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现”out of memory错误”

      为什么一些程序频繁发生GC?有如下原因:

      (1)程序内调用了System.gc()或Runtime.gc()。

       (2)一些中间件软件调用自己的GC方法,此时需要设置参数禁止这些GC。

      (3)Java的Heap太小,一般默认的Heap值都很小。

      (4)频繁实例化对象,Release对象。此时尽量保存并重用对象,例如使用StringBuffer()和String()。

      如果你发现每次GC后,Heap的剩余空间会是总空间的50%,这表示你的Heap处于健康状态。许多Server端的Java程序每次GC后最好能有65%的剩余空间。

      JVM 使用的GC算法是什么?

      分代收集。即将内存分为几个区域,将不同生命周期的对象放在不同区域里;

      在GC收集的时候,频繁收集生命周期短的区域(Young area);

      比较少的收集生命周期比较长的区域(Old area);

      基本不收集的永久区(Perm area)。

      GC何时会被触发?
      (1)系统空闲:GC线程的优先级低于系统应用线程,当系统中没有应用线程执行时,GC会被触发。
      (2)堆空间内存不足:当堆空间的内存不足以创建新对象时,GC会被触发。如果第一GC仍不能获得足够的空间,第二次GC将被触发,如果这一次仍无法获取足够的空间,“Out of memory”将被抛出。

  • 相关阅读:
    SqlServer与Access之间的数据互导
    [转]半角<=>全角互转函数[JS版 VBS版]
    [文摘20070914]一个成功的博客必须知道的80个博客工具
    在javascript中获得由Ajax返回DataTable的列数和列名
    [转]获取xml节点值和属性值(兼容ie和firefox)
    [文摘20070920]网络战
    游标简单使用
    sql函数 得到 由 年月日时分秒+三位内的随机数 组成的随机数
    [转]ASP.NET 2.0 AJAX中Webservice调用方法示例 (包含参数类型为DataTable的WS方法)
    向页面中添加音乐或flash
  • 原文地址:https://www.cnblogs.com/shaweng/p/4029228.html
Copyright © 2020-2023  润新知