zoukankan      html  css  js  c++  java
  • JVM内存模型

    下图说明JVM内存模型和JVM参数的关系:

    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”将被抛出。

  • 相关阅读:
    HUST 1372 marshmallow
    HUST 1371 Emergency relief
    CodeForces 629D Babaei and Birthday Cake
    CodeForces 629C Famil Door and Brackets
    ZOJ 3872 Beauty of Array
    ZOJ 3870 Team Formation
    HDU 5631 Rikka with Graph
    HDU 5630 Rikka with Chess
    CodeForces 626D Jerry's Protest
    【POJ 1964】 City Game
  • 原文地址:https://www.cnblogs.com/linghu-java/p/5725066.html
Copyright © 2011-2022 走看看