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


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堆和方法区的垃圾收集器
年轻代GC触发条件
  • 当年轻代内存不足时,会触发Minor GC,这里的内存不足指的是Eden区的内存不足,Survivor区不会 。
  • Minor GC 会暂停其他用户的线程,等到垃圾回收结束,用户的线程才恢复 。
老年代GC触发条件
  • 老年代空间不足时,会尝试触发Minor Gc,如果空间还是不足,则会触发Major GC
  • 如果Major GC结束后,空间还是不足,会报OOM异常 。
  • Major GC的速度比Minor GC慢10倍以上 。
Full GC触发条件
  • 程序调用System.gc(),会触发Full GC,但不会立即去执行 。
  • 老年代空间不足 。
  • 方法区空间不足 。
  • 通过Minor GC后仍能进入老年代的对象所占空间大于老年代剩余可用空间 。
5.元空间JDK1.8后为什么废除永久代,引入元空间
  • 在之前的永久代中,它是堆的一部分,主要是在存储类的元数据、静态变量、常量等,这些数据的大小也不太容易控制和计算,开发人员对永久代进行调优会有很多的难度 。永久代会对GC带来不必要的复杂度,回收效率偏低 。
  • 而用元空间替代永久代,这样的话可以很好的解决这个问题,因为元空间是放在本地内存上的,简而言之,只要你服务器内存还有,元空间基本就不会发生内存溢出等问题 。
废除永久代的好处
  • 由于类的元数据分配在本地内存上,这样就说元空间的最大分配内存就是服务器系统剩余可用内存,不会遇到永久代时存在的内存溢出问题 。
  • 将运行时常量池从永久代中分离出来,与类的元数据分开,提高了元数据的独立性 。
  • 将元数据从永久代剥离出来放到元空间,可以提升对元数据的管理,同时也提升GC效率 。
元空间相关参数