JVM 垃圾回收机制主要原理

JVM 垃圾回收机制主要原理对于垃圾JVM的垃圾回收机制这里我们称为GC,众所周知,java语言不需要像c++那样需要自己申请内存,自己释放内存,这些都是JVM帮我们做好了的,但是对于一名java程序员,想要更近自己的水平更上一层楼,就要去了解GC的工作原理,根据原理才能写出更好的更优的程序,这里我们先初步讲解一下GC的工作原理首先我们在讲解之前我们需要了解一下JVM内存运行时数据区的三个重要的地方堆(heap)

大家好,又见面了,我是你们的朋友全栈君。

对于垃圾JVM的垃圾回收机制这里我们称为GC,众所周知,java语言不需要像c++那样需要自己申请内存,自己释放内存,这些都是JVM帮我们做好了的,但是对于一名java程序员,想要更近自己的水平更上一层楼,就要去了解GC的工作原理,根据原理才能写出更好的更优的程序,这里我们先初步讲解一下GC的工作原理


首先我们在讲解之前我们需要了解一下JVM内存运行时数据区的三个重要的地方

  • 堆(heap) : 他是最大的一块区域,用于存放对象实例和数组,是全局共享的.
  • 栈(stack) : 全称为虚拟机栈,主要存储基本数据类型,以及对象的引用,私有线程
  • 方法区(Method Area) : 在class被加载后的一些信息 如常量,静态常量这些被放在这里,在Hotspot里面我们将它称之为永生代

关于具体结构可以用下面这张图来对内存运行时数据区有一个大致的概括
这里写图片描述

堆(heap):,前面已经说了他是最大的,也是最重要的一块区域,这里也称为逻辑堆,主要用来存放对象实例与数组,对于所有的线程来说他是共享的,对于Heap堆区是动态分配内存的,所以空间大小和生命周期都不是明确的,而GC的主要作用就是自动释放逻辑堆里实例对象所占的内存,而在逻辑堆中还分为新生代与老年代,用来区分对象的存活时间,在新生代中还被细致的分为 Eden SurvivorFrom以及SurvivorTo这三部分.


方法区(Method Area):方法区主要存储(类加载器)ClassLoader加载的类信息,在这里我们可以理解为已经编译好的代码储存区,所以存储包括类的元数据,常量池,字段,静态变量与方法内的局部变量以及编译好的字节码,等等

栈(stack):在每一个对象被创建的时候,在堆栈区都有一个对他的引用,在这里我们可以这样理解。

Object obj = new Object();

上面的代码左边的Object obj 等于在堆栈区申请了一个内存,这里也就是对类的引用了,而 new Object()则是生成了一个实例,=则是 将对象的内容则可通过obj进行访问,在Java里都是通过引用来操纵对象的。

pc寄存器(PC Regesiter): 在多线程中,系统需要给每一个线程 分配一个进程编号,这个时候才会需要到寄存器。


好了 基本的都介绍完了,现在来进入正题 :

我们知道对象的实例是存在于逻辑堆中,而GC在逻辑堆是怎样运行的呢,下面我们看下逻辑堆的具体结构
这里写图片描述
就像上面的图可以看出 逻辑堆分为 年轻代与年老代,对于非堆内存这里先不讲解,而年轻代则被分为 eden survivor1 survivor2 ,对于一个新被实例化的对象都是存在于年轻代中的eden区,至于为什么,下面会讲到,eden中文名为伊甸园,按照GC的运行机制,会回收掉已经死掉的对象,而对象一般都是在年轻代就会死去,所以年轻代比老年代需要更频繁的GC清理,下面针对年轻代与老年代的回收机制有不同的讲解

年轻代 :

在年轻代中jvm使用的是Mark-copy算法,就像算法名字说的那样有两个步骤,第一是标记(Mark) 第二是copy(复制),Mark主要用于标记出还活着的实例,然后清除掉没有被标记的实例,释放内存,然后Copy部分则是将还活着的实例根据年龄拷贝到不同的年龄代,而jvm又是根据什么来区分年龄代,和实例存活与不存活的呢? 下面将对这个过程进行讲解


对于标记 与区分年龄代的技术 我们一般都是用到的都是引用计数器,在每一个对象中都含有引用计数器,都有引用指向对象的时候 引用计数器就会加1,不在被引用 计数器 减 1,对与垃圾回收的策略则是标记所有活着的实例,将没有被标记的实例全部回收 释放内存,


对于静态,我们都知道静态方法与静态变量是不会产生实例的,直接通过类的引用,使用 ClassLoader进行加载的类数据如前面所说是不存在逻辑堆里面的,直接存在于永生代里面也就是 方法区里面,这个类一旦被清除掉里面所有的静态变量都会被清除

当我们在 Object obj 的时候 向逻辑堆中的 Eden区域 申请内存,当Eden区域的内存不足的时候,这个时候会触发GC这个时候称gc为小型垃圾回收,每个实例都有一个独有的年龄,每个引用被经历过一次GC后就会年龄加一,同时就会将没有被清理掉的对象全都copy到上图的survivor1区域,如图1所示:
这里写图片描述
当第二次GC执行的时候就会使用Mark算法找到存活的对象,然后将他们的年龄加1,并且将他们拷贝到survivor2区域,然后执行GC,这样就可以实现survivor1 与 survivor2 两个一样大的区域进行交替使用,当对象的年龄足够大的时候,对象就会被移动到老年代,这里移动到老年代的标准由JVM的参数所决定

年老代 :

当GC被触发的时候 eden的对象会转到 survivor1 然后再次就会转到 survivor2 ,当survivor1的对象太大了 survivor2的区域无法容纳得部分就会转到Tenured的区域,当Tenured的区域也容不下的时候就会自动移动到年老代,在移动年老代的时候会先触发年老代上面的GC然后在将Tenured容纳不下的对象放入年老代,对于年老代的GC算法与年轻代的Mrak-copy算法有很大不同

年老代的GC算法在jdk 1.7 中分为五种,

Serial GC
Parallel GC
Parallel Old GC(Parallel Compacting GC)
Concurrent Mark & Sweep GC (or “CMS”)
Garbage First (G1) GC

在这里我只讲解两种Parallel Scavenge 与 Concurrent Mark sweeps 对与这两种接下来会进行简单的讲解

Parallel Scavenge :

在这里我们简称他为PS算法,PS算法执行的是 Mark-compact算法的过程 ,并且是用多线程进行执行这样提高了执行效率,这里的Mrak还是与之前的年轻代的Mark原理是一样的,但是Compat算法则是将年老代的对象进行碎片化的整理,并且年老代是没有像年轻代的那样有survivor1 与 survivor2来将残留的对象全部copy过去,考虑到年老代的对象比较多,所以就需要进行碎片化整理如下图:
这里写图片描述

Concurrent Mark sweeps:

我们简称他为 CMS 算法,对与cms算法,我们先需要了解一个概念 Stop the world,对于Stop the world,不管选择哪种GC算法,stop-the-world都是不可避免的。Stop-the-world意味着从应用中停下来并进入到GC执行过程中去。一旦Stop-the-world发生,除了GC所需的线程外,其他线程都将停止工作,中断了的线程直到GC任务结束才继续它们的任务。GC调优通常就是为了改善stop-the-world的时间。在CMS GC开始时的初始标记(initial mark)比较简单,只有靠近类加载器的存活对象会被标记,因此停顿时间(stop-the-world)比较短暂。在并发标记(concurrent mark)阶段,由刚被确认和标记过的存活对象所关联的对象将被会跟踪和检测存活状态。此步骤的不同之处在于有多个线程并行处理此过程。在重标记(remark)阶段,由并发标记所关联的新增或中止的对象瘵被会检测。在最后的并发清理(concurrent sweep)阶段,垃圾回收过程被真正执行。在垃圾回收执行过程中,其他线程依然在执行。得益于CMS GC的执行方式,在GC期间系统中断时间非常短暂。CMS GC也被称为低延迟GC,

关于GC的原理就讲到这里了,这篇博客只讲解了最基本的GC 接下来要学习的还有更多,加油吧

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/132468.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 彩色图像–伪彩处理 灰度图转伪彩色图像

    彩色图像–伪彩处理 灰度图转伪彩色图像

  • python做cae库_python常用模块-OS模块

    python做cae库_python常用模块-OS模块importos__file__:指当前文件,带有路径的D:/svn_auto3/test_case1/test1.py(注意这里的斜杠,和abspath的区别就是这里)#路径操作>>>os.chdir(‘D:\\’)#进入目录#目录切换操作>>>importos>>>os.curdir’.’>>>os.pardir’…

  • Fiddler安装教程(图文版)「建议收藏」

    Fiddler安装教程(图文版)「建议收藏」本章教程,主要介绍如何在windows10系统上安装Fiddler。一、Fiddler软件简介二、软件官网地址三、图文下载步骤四、软件安装步骤五、结语一、Fiddler软件简介Fiddler是一个http协议调试代理工具,它能够记录并检查所有你的电脑和互联网之间的http通讯,设置断点,查看所有的“进出”Fiddler的数据(指cookie,html,js,css等文件)。Fiddler要比其他的网络调试器要更加简单,因为它不仅仅暴露http通讯还提供了一个用户友好…

    2022年10月22日
  • Delphi中谨慎使用QuotedStr、QuotedString、DequotedString相关的函数

    Delphi中谨慎使用QuotedStr、QuotedString、DequotedString相关的函数//以下测试代码vars,ss:string;begin//1.添加定界符(内容中含定界符的要转义)ss:=QuotedStr(s);//单引号ss:=s.QuotedString(””);//单引号//2.添加指定的定界符(内容中含定界符的要转义)ss:=AnsiQuotedStr(s,'”‘);//双引号ss:=s.QuotedString(‘”‘);//双引号//3.去掉定界符(内容中含连续两个定界符的要反转义)…

    2022年10月18日
  • ACL 通配符掩码的应用「建议收藏」

    ACL 通配符掩码的应用「建议收藏」ACL(Access Control List) 访问控制列表在作为数据包的过滤器以及在对指定的某种类型的数据包的优先级,起到了对某些数据包的优先级起到了限制流量的作用,减少了网络的拥塞。          通配符掩码作为ACL中重要的一部分,是路由器在进行访问控制时必不可少的重要部件,那么什么是通配符掩码呢?          通配符掩码:路由器使用通配符掩码与原地址或者是目标

  • 一文解释清卷积神经网络中池化层的作用「建议收藏」

    池化层:池化层夹在连续的卷积层中间,用于压缩数据和参数的量,减小过拟合。简而言之,如果输入是图像的话,那么池化层的最主要作用就是压缩图像。池化层分为3类,平均池化,最大池化和随机池化。拿最大池化举个例子:上图的例子是按步幅2进行2X2的最大池化时的处理顺序。最大池化是获得最大值的运算,“2X2”表示目标区域的大小。如上图所示,从2X2的窗口的移动间隔为2个元素。另外,一般来说,池化的窗口大小会和步幅设定成相同的值。比如3X3的窗口的步幅会设为3,4X4的窗口的步幅会设为4等。而最大池化的优点是:

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号