JVM-垃圾回收机制(初识)

概述
Jvm运行时各数据区介绍
程序计数器

虚拟机栈
本地方法栈
方法区
内存分配与回收策略
引用计数器法
可达性分析算法
标记-复制算法
标记-整理算法
复制算法
分代来及回收

概述
  • 所谓的Java程序依次编写,处处运行,是由于Java的跨平台原理,是因为在不同平台上的虚拟机决定的,因此Java文件的执行不直接在操作系统上执行,而是在虚拟机上执行

在这里插入图片描述

jvm运行时数据区介绍
  • 执行Java文件时首先由javac命令翻译成.clas字节码文件,通过类加载器加载到运行时数据区,由于Java命令操作系统是不可以直接识别的,通过搜索引擎调用本地接口翻译成可被操作系统识别的命令

在这里插入图片描述

在这里插入图片描述

程序计数器
  • 程序计数器线程私有,每个线程都有一个独立的程序计数器, 运行时数据区里唯一的不会发生数据泄露。
  • 创建一个对象实例或是创建数组时会在堆开辟一个内存空间,连续创建时堆内存物理地址不一定连续(只要逻辑连续即可),若内存不够会发生内存泄漏

在这里插入图片描述

虚拟机栈
  • 虚拟机栈线程私有 对于基本数据类型,long和double型变量占用俩个局部变量大小,其余的占用一个,方法创建时会伴随着一个栈帧,方法入栈,当执行结束时,方法弹栈,栈帧结束引用数据类型创建一个数据对象时,引用变量指向对象开辟空间地址的起始位置在编译期间所占内存大小即确定
  • 运行时因为从main方法开始执行,所以main方法入栈底,在方法体中的数据域变量入栈,然后子方法入栈,当子方法执行结束时,弹栈,知道main方法执行结束后,弹栈
  • 栈方法特点,先进后出
  • 虚拟机栈描述的是Java方法的执行模型
  • 线程私有:虚拟机栈、程序计数器、堆

在这里插入图片描述

本地方法栈
  • 本地方法栈和虚拟机栈类似,不同的是本地方法栈执行native方法,不是用Java语言实现的,而是直接和操作系统打交道,入c或c++,只是供Java调用,也可能会发生栈溢出
方法区
  • 可能会发生数据异常
堆内存异常
  • 递归函数没有出口会发生栈异常
内存分配与回收策略
判断对象已死的方法
  • 引用计数器法

给对象添加一个引用计数器,当该对象被引用时,引用计数器加1,当引用消失时,引用计数器减1,任意时刻,当引用计数器为0时,该对象不在被引用。(python中常用此算法,但是Java中很少用,因为当循环引用时对象A引用B,对象B引用A,jvm会束手无策)(循环引用:只存在俩个对象相互引用)

  • 可达性分析算法

在主流的语言中(c和c#)都是通过可达性分析算法来判断对象是否存在。这个算法思想就是通过一系列成为"GC ROOTS"的对象作为起点,从这些节点开始向下搜索,所走过的路径称为引用链,当一个对象到"GC ROOTS"没有任何引用链相连时,则证明此对象时不可用的

在这里插入图片描述

  • GC会回收那些不是GC ROOTS且没有被GC ROOTS引用的对象
  • 在Java中可以作为GC ROOTS的引用对象如下
    虚拟机栈中引用的对象
    方法区中静态属性引用的对象
    方法区中常量引用的对象
    本地方法区中JNI(即常说的Native方法)的引用对象

在这里插入图片描述

标记-清除算法
  • 缺点:此算法造成大量的内存碎片,造成资源浪费
  • 先标记、后清楚、标记清除效率都不高

在这里插入图片描述

标记-整理算法
  • 此算法会先将存活对象整理出来,整理完毕之后,会设置一个指针,会将指针后的对象全部清除(但商用虚拟机很少采用一种算法)

在这里插入图片描述

复制算法
  • 先将内存区域复制一份当做预留区,此区域不存放任何对象,然后将对象移动到预留区域,全部移动完毕之后,将左面的区域擦除,作为预留区域
  • 复制算法解决了内存碎片的问题,但是每次都要预留50%的存,造成内存浪费

在这里插入图片描述

分带垃圾回收
分带垃圾回收总的来说分为2个区,然后再细分
  • 新生代(8:1:1)

    • Eden(伊甸园区)
    • Survivor(幸存区)
      • from区
      • to区
  • 老年代

  • 年轻代:存放垃圾收集频率较高,产生的块,回收的也快( 朝生夕死)

  • 老年代:经常用的,不容易被回收的有价值的在老年代

  • 80%对象都是朝生夕死的

  • 过程

    • 新产生的对象在伊甸园区,
    • 将标记存活的对象复制到from区,然后将伊甸园区所有对象做一次垃圾处理(复制算法),此时第一次存活对象来到from区标记1
    • 又有大量新生对象产生在伊甸园区,此时将伊甸园区和from区标记的存活对象复制到to区,此时年龄各自加1,然后将伊甸园区和from区对象做一次垃圾处理
    • 又有大量新生对象产生在伊甸园区,此时将伊甸园区和to区标记存活的对象复制到from区,然后将伊甸园区和to区做一次垃圾回收
    • from区和to区是来回移动,始终保持只有一个区存放对象
    • 每次都是采用复制算法,始终保持有90%区域产生新生对象,10%区域来存放存活对象
  • 内存担保机制(Minor GC),当10%区域不够存放存活对象时,会将存活对象放到老年代15岁以后的对象也进入老年代

  • 当新生代和老年代都不够存放对象时,会将这俩个区域做一次垃圾回收(Full GC)

  • 总结:

    • 在新生代,每次都有大量的对象死去,只有少量的对象存活,这就适合采用复制算法,只需要付出少量的复制算法成本就可以完成垃圾回收
    • 而老年代因为存活率较高没有其它内存进行分配担保,就必须采用标记-清除 或标记-整理进行回收
  • 垃圾回收机制总结:

    • 分代分为年轻代和老年代,年轻代又可分为Eden区和Survivor区默认比例8:1:1,每次预留10%内存作为预留区域然后将90%区域用来作为产生新生对象
    • 每一次垃圾回收,存活的对象 +1 当经历15此还仍然存活的对象,让它进入老年代
    • 另一种进去老年代的方式是内存担保机制,当新生代的内存不够产生新生对象时,对象直接进入到老年代
    • 新生代的垃圾回收叫做Mino Gc,老年代叫做 Full Gc
  • 垃圾收集器

  • 新生代垃圾收集器

    • Serial收集器在jdk1.3之前是新生代垃圾回收的唯一选择,这个收集器是一个单线程,它的单线程并不是说它只会私用一个CPU或是一条手机线程区完成收集工作,在进行垃圾回收时,其它工作线程会暂停,直到收集结束。client模式下首先新生代收集器

在这里插入图片描述

  • ParNew收集器
  • ParNew收集器是Serial收集器的多线程版本,除了使用多线程进行垃圾回收之外,其余的可控参数,收集算法,停止工作线程与Serial一样。Server模式下首选新生代收集器

在这里插入图片描述

  • Parallel Scavenge收集器
  • Parallel Scavenge收集器采用的是并行多线程新生代垃圾收集器,Parallel Scavenge收集器可达到控制的吞吐量,所谓吞吐量就是cpu运行用户线程的时间与cpu运行总时间的比值
  • 老年代处理器
    • Serial Old处理器
    • Serial Old是Serial收集器的老年代版本的单线程处理器,使用标记-整理算法,这个处理器的主要目的也是在client模式下使用
    • CMS收集器
      • CMS是一种获取最短停顿时间为目标的收集器,采用标记-清除算法,过程分为4个步骤,只有初始标记和重新标记需要暂停用户线程
      • 初始标记,仅仅关联GC Roots能直接关联到的对象,速度很快
      • 并发标记,进行GC Roots Tracing的过程
      • 重新标记,为了修正并发标记期间,因用户程序运作而导致标记产生变动的那一部分的对象标记记录
      • 并发清除

在这里插入图片描述

  • CMS处理器三大缺点
    • CMS收集器队cpu非常敏感
    • 无法处理浮动垃圾
    • 因为基于标记-清除算法,会有大量的垃圾碎片产生
jvm参数表

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值