详细了解JVM运行时内存( 二 )


4.1.2 特点

  • 堆是Java虚拟机所管理内存中最大的一块区域 。
  • 堆是线程共享的 。
  • 堆在虚拟机启动的时候创建 。
  • 堆存在的目的就是存放对象实例 。
  • 堆是垃圾回收管理的主要区域 。因此堆又被称作为GC堆,JAVA堆还可以细分为新生代,老年代,永久代(jdk8以后就取消了),其中新生代又分为Eden空间、From survivor、To survivor 。
  • 堆在计算机物理上存储是不连续的,但是逻辑上是连续的,它的大小可以调节(-Xmx,-Xms控制) 。
  • 方法结束后,堆对象不会马上的移除,仅仅在垃圾回收的时候才会移除 。
  • 如果堆中没有足够的内存完成对实例的分配,且堆的空间无法再扩展时,那么将会报出OOM异常 。
4.1.3 设置堆内存大小我们可以通过-Xms来设置最小堆内存,通过-Xmx设置最大堆内存 。
详细了解JVM运行时内存

文章插图
以上是设置了:-Xms5m -Xmx20m
这里可以看出打印出来的Xmx值18m和设置的值20m之间是有差异的,total Memory和最大的内存之间也还是存在比较明显的差异,就是说JVM一般会尽量保持内存在一个尽可能底的层面,而非贪婪做法按照最大的内存来进行分配 。
另外 , 当我们申请分配内存10m时,我们会发现free Memory和total Memory都上升了,可以看出JVM在内存分配时是动态分配的 。
4.1.4堆的分类JAVA将虚拟机堆分为三个部分:
  • 新生代 (又分为伊甸园区 , 幸存者区s0和幸存者区s1)
  • 老年代
  • 永久代(JDK1.8后没有了,被本地内存的元空间取代了)
图例如下:
详细了解JVM运行时内存

文章插图

详细了解JVM运行时内存

文章插图
4.2 新生代和老年代4.2.1 对象存储
  • 新生代存放刚创建的实例对象 , 内存比较小,垃圾回收比较频繁 。新生代又分为Eden区,survivor To区S0和survivor From区S1,其中S0区和S1区并不是固定的from及to的区域,由对象转移的方向决定的 , 假设对象从S1转移到S0,那么S1便是survivor From , S0是survivor To 。
  • 老年代主要存放一些生命周期比较长的对象,经过在新生代几次的回收依旧没有清除掉,那这部分实例便会转移到老年代 。老年代的垃圾回收相对来讲没有那么频繁 。
4.2.2 配置新生代和老年代的堆中占比默认情况下-XX:NewRatio=2,表示新生代:老年代 = 1:2,新生代占整个堆空间的1/3
案例:假设我们将-XX:NewRatio修改为等于4,那么则表示新生代:老年代 = 1:4 , 那么新生代占整个堆空间的1/5
除了我们可以配置新生代和老年代的比例之外,我们还可以配置eden和S0和S1在新生代中的占比情况,默认情况下-XX:SurvivorRatio = 8,表示Eden:S0:S1=8:1:1,这表示Eden占整个新生代的8/10,而两个survivor区域分别占了1/10,另外,需要补充一点 , 由于JVM在运行时,每次都只会使用Eden区和一块survivor区进行服务,因此总是会有一个survivor区域是空闲着的,所以新生代的最高使用也只能达到9/10 。
4.3 对象分配过程
  • new对象时首先会将对象放在eden区,该区大小有内存限制 。
  • 当eden区的数据满了之后 , 程序还需要创建对象,会触发垃圾回收,将那些不再被引用的对象给销毁掉 。
  • 剩余没被回收掉的对象会被转移到S0区,而程序新创建的对象又会继续写入Eden区 。
  • 当再次发生垃圾回收时,如果S0中还存在未被销毁的对象,那么这部分剩余的对象会被转移到S1中 。
  • 之后每次经历垃圾回收,存在S0或者S1中未被销毁的对象总会相互转移过去 。
  • 当这种转移达到15次上限后,那么这部分对象将会被转移到老年区 。当然这个阈值并不是固定15,可以通过调节参数 -XX:MaxTenuringThreshold=N来控制阈值 。
  • 当养老区的内存也不足时,会触发GC进行养老区的垃圾回收 。
  • 如果养老区进行了GC垃圾回收后还是没有办法保存新创建的对象,那么将会报OOM异常 。
4.4 堆GCJava中的堆是虚拟机中GC收集垃圾的主要区域 。GC分为两种 , 一种是部分收集(Partial GC),一种是整堆收集(Full GC).
部分收集
  • 新生代收集(Minor GC/Yong GC):只是新生代的垃圾回收 。
  • 老年代收集(Major GC/Old GC):只是老年代的垃圾回收 。
  • 混合收集(Mixed) :收集整个新生代和老年的垃圾 。(G1 GC会混合回收, region区域回收)
整堆收集(Full GC):收集整个java堆和方法区的垃圾收集器

推荐阅读