JVM调优由浅到深(三)——垃圾回收

垃圾回收的区域

一般发生垃圾回收是在java堆中,所以我们重点讲java堆

java堆

java堆可以说是Java运行时内存中最为重要的部分,几乎所有的对象和数组都是在堆中分配空间的。
Java堆分为新生代和老年代两个部分,
新生代用于存放刚刚产生的对象和年轻的对象,如果对象一直没有被回收,生存得足够长,就会被移入老年代。

垃圾回收把对象划分为几个部分

垃圾回收把对象划分为了新生代,年老代,永久代(元空间)。

新生代

新生代又可进一步细分为
eden、
survivor space0(s0 或者 from space)
survivor space1(s1或者to space)。

eden:对象的出生地,大部分对象刚刚建立时,通常会存放在这里。
s0 和 s1 为 survivor(幸存者)空间,存放其中的对象至少经历过一次垃圾回收,并得以幸存。如果在幸存区的对象到了指定年龄仍未被回收,则有机会进入老年代(tenured)。

在这里插入图片描述

年老代

年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期较长的对象。

永久代

用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class。

元空间

JDK8 HotSpot JVM 将移除永久区,使用本地内存来存储类元数据信息并称之为:元空间(Metaspace)。

元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。

元空间理论上取决于32位/64位系统可虚拟的内存大小。不过,可以通过设置参数 MaxMetaspaceSize 限制本地内存分配给类元数据的大小。如果没有指定这个参数,元空间会在运行时根据需要动态调整。

讲到这里我们应该再说下方法区。
方法区是运行时数据区的一部分,方法区是JVM的一种规范,永久区是一种具体实现,元空间也是一种具体的实现。

在JDK8之前的Host Spot虚拟机的实现中,方法区也被称为永久区,是一块独立于 Java 堆的内存空间。
虽然叫永久区,但是永久区中的对象同样可以被 GC 回收的。对永久区 GC 的回收,通常主要从两个方面分析:一是 GC 对永久区常量池的回收;二是永久区对类元数据的回收。永久区的垃圾回收是和老年代(old generation)捆绑在一起的,因此无论谁满了,都会触发永久代和老年代的垃圾收集。

在 Java8 中,永久区已经被 Metaspace 元空间取而代之。
原永久区的数据被分到了堆和元空间中:
元空间存储类的元信息,静态变量和常量池等放入堆中。
相应的,JVM参数 PermSize 和 MaxPermSize 被 MetaSpaceSize 和 MaxMetaSpaceSize 取代。

元空间的配置详细说明如下:

  -XX:MetaspaceSize:
  初始空间大小,达到该值就会触发垃圾收集进行类型卸载,
  同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;
  如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。
  
  -XX:MaxMetaspaceSize:
  最大空间,默认是没有限制的。

 除了上面两个指定大小的选项以外,还有两个与 GC 相关的属性:
  -XX:MinMetaspaceFreeRatio:
  在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集
  
  -XX:MaxMetaspaceFreeRatio:
  在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集

为什么1.8要移除永久区,改为元空间??

  • 字符串存在永久代中,现实使用中易出问题, 由于永久代内存经常不够用或发生内存泄露,爆出异常 java.lang.OutOfMemoryError: PermGen

  • 类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。

  • 永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。

什么时候会出现 java.lang.OutOfMemoryError: Metaspace,这种内存溢出的问题?
因为大量调用接口,而接口又用到了反射类加载器ClassLoader。
而且Metaspace中类的元数据信息只有在加载它的ClassLoader被释放后才会发生写在,如果ClassLoader对象一直存活,那么它所加载的类的元数据信息将不会被卸载。

可以参考以下博客

https://www.jianshu.com/p/1a0b4bf8d498
https://blog.csdn.net/a15939557197/article/details/90635460

GC图

在这里插入图片描述

gc类型分为:minor gcmajor gc ,major的速度比minor慢10倍至少

发生在 young(主要是Survivor)区的gc称为 minor gc
发生在 old(Tenured)区的gc称为 major gc
发生在新生代和老年代的gc称为 full gc

会发生的异常

一般垃圾回收会发生两个异常
1)OutOfMemoryError
2)StackOutflowError

如图

图片来自网络
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值