jvm的概念理解以及G1,GMS垃圾回收机制的理解

  1. jvm中的内存机制
    1. jvm的内存空间分为两大区域,一个堆一个栈,堆里面放着new出来的东西,还有数组对象也会在堆里,栈中放的是对象的引用,栈里面的引用去指向堆空间new出来的地址的首地址,这样的话就可以找到它的位置,进行数据存储。
    2. jvm开内存是在堆中去开,因为它的堆是非常大的,堆里面有这么几个区域,青年带,老年带。青年带里面有伊甸园区,开辟的所有对象都会在伊甸园区,当伊甸园区的内存不够时,它会自己去到堆空间中的老年带里去加,这时候,如果判断创建的对象要比老年带里的还大,则抛出异常。这个是jvm的内存溢出,它和数据库的内存溢出不太一样,数据库的话是会把超量的数据直接往内存里去塞,知道内存满了,抛出异常,这条数据库的连接作废,因为数据库其他操作也走这条操作路线,一个卡死,其他都会卡死。
    3. 然后在堆中还会有一个空间,它存储的是类信息,静态资源和常量,这里面的数据我们放到元空间,元空间是堆中的一块区域,但他却叫做非堆区,元空间里面的数据和对空间里面的数据在线程概念中是一样的,叫做线程共享,所以静态资源,类信息和常量还有new出来的对象,数组都会有线程安全问题。
    4. 数据类型没有线程安全问题,栈里面数据是线程私有的。
    5. 程序计数器
      1. 线程私有,没有线程安全问题,因为是多线程的,比如现在在主线程里去运行,我开一条线程,现在这条线程被别的任务占用了,那么程序计数器会在这条线程开始运行的地方打一个标记,线程运行完了回来了之后,主线程会接着计数。
    6. 本地方法栈
      1. 本地方法栈中没有所谓的方法,本地方法栈里面是我们java底层核心中的HotSpot(虚拟机)里面的方法,比如我们java是没有开发内存操作的,但是我们Native里面的方法是直接操作内存的。就是底层的操作内存的方法是在本地方法栈里面。一般Native底层是用c编写的,交互底层硬件。
    7. 方法栈
      1. 方法栈进行弹栈和压栈,调用了一个方法就会进行压栈,方法执行完了会进行弹栈。
    8. 内存回收机制
      1. 一个对象在伊甸园区没有被回收的话,S0,S1在回收的时候进行交换操作,他会从S0进到S1区如果回收一次之后,对象还在,则S1到S0。越不被清除的对象越不好回收,假如它每次都避过去了。第一种方法是手动置null。第二种就是对象进入老年带,所有没有被回收的对象都要进入老年带。老年带要做的事情就是要把没有回收的对象全部进行左移,左移到老年带区域。它每次去进行回收的时候都会对数据进行标记,标记15次,在第16次回收的时候,一定会回收掉。
      2. 为什么不在老年带直接就把对象回收了呢
        1. 因为回收这件事是很耗内存的,每次回收都会造成java挂起状态,经常回收,程序运行会变慢,所以回收的话是按照垃圾回收器里的规则进行回收。
      3. 垃圾回收器
        1. 按照线程分:串行和并行
        2. 按照功能分:并发和独占
        3. 按照碎片处理方式分:压缩式和非压缩式,压缩式垃圾回收会在回收完成之后对存活对象进行压缩整理,消除回收后的碎片。非压缩式不会。
        4. 按照工作区间分:年轻带和老年带
        5. 性能指标:
          1. 吞吐量:运行代码时间占总运行时间的比例
          2. 暂停时间:执行垃圾收集时,程序的工作线程被暂停的时间
          3. 内存占用:java堆区所占内存大小
        6. 设计方向,在大吞吐量优先的情况下,降低停顿时间
        7. 常见的垃圾回收器
          1. 串行回收器:Serial,SerialOld
          2. 并行回收器:ParNew,ParalleScavenge,ParallelOld
          3. 并发回收器:GMS,G1
        8. 回收器在垃圾分代分布
          1. 年轻带:Serial,ParalleScavenge,ParNew,G1
          2. 老年带:SerialOld,ParallelOld,GMS,G1
          3. G1是整堆回收,单线程回收,具有Nio代理,GMS是老年带回收,多线程挂起回收
        9. GMS并发收集器
          1. 标记清除算法
            1. 初始标记:程序短暂暂停,该阶段主要标记出Roots能直接关联到的对象。
            2. 并发标记:该阶段是要根据上个阶段标记的对象扫描整个对象图,耗时较长,但是可以和用户线程同时执行。
            3. 重新标记:该阶段为了修正并发期间,用户修改的对象的记录,耗时短于并发长于初始标记,需要程序暂停。
            4. 并发 清理:该阶段对标记好的对象进行清理,和用户线程同时执行。
          2. GMS是在jdk9之前使用的一款GMS,现在市面上大都采用的都是这个。但是GMSGC会有弊端
            1. 做不到完全的并发,只能算低停顿
            2. 做不到老年带完全填满再收集,只能设置一个阈值再进行回收,如果预留的内存不足以满足程序的运行,则会报错,这时候系统会临时启动SerialOld默认的老年带GC,这样耗时就更长了。
            3. 在并发期间会可能有用户对标记的垃圾进行修改,所以会产生碎片。
        10. GMS在jdk9中被移除,官方选择废弃。而将G1 全功能收集器放在之后的版本中。
          1. G1介绍
            1. 分代上看,G1仍旧属于分代处理,只不过在堆的结构上,各代的分区不在坚持连续,固定大小和数量。而是分为若干区域(Region),这些区域包含了逻辑上的各个分代。
            2. Garbage First,是一个并行回收器,他把堆内存分割成许多不连续的区域,使用不同的区域来表示S0(幸存者0区),S1(幸存者1区),老年带等。
            3. G1有计划的避免了在整个java堆中进行全区域的垃圾收集,转以跟踪各个区域的垃圾堆积价值大小(回收后获得的空间大小和回收所需要的时间),在后台维护一个优先级列表,根据允许的收集时间,优先回收价值最大的那块区域。
            4. 因为该回收机制侧重于回收垃圾最大量的区间,所以也可以称为垃圾优先机制。
          2. G1优劣势
            1. 该收集器在对比GMS还不具备压倒性优势,在小内存应用上GMS还是会优于G1,G1在大内存应用上发挥着优势,平衡点在6-8G之间。
          3. G1优势
            1. G1主要面向服务器,针对配备了多核cpu以及大容量内存的机器。1.7版本正式启用。该回收器同其他回收器不同,它兼顾了年轻带和老年带。被官方称为全功能的垃圾收集器,
            2. 并行性,G1回收期间,可以多个GC线程工作,多核的计算能力
            3. 并发性,工作任务和回收任务9比1执行,一般来说在回收期间不会阻塞工作任务。
            4. 不再坚持于内存连续,固定大小,固定数量的分代,实行堆空间被分为若干(Region)区域的逻辑分代
          4. 参数设置
            1. -XX:+UseG1GC手动指定使用G1收集器执行内存回收任务。
            2. -XX:G1HeapRegionsize设置每个Region的大小。值是2的幂,范围是1MB到32MB之间,目标是根据最小的Java堆大小划分出约2048个区域。默认是堆内存的1/2000。
            3. -XX:MaxGCPauseMillis设置期望达到的最大GC停顿时间指标(JVM会尽力实现,但不保证达到)。默认值是200ms.
            4. -XX: Paralle1GCThread设置STW工作线程数的值。最多设置为8
            5. -XX:ConcGCThreads设置并发标记的线程数。将n设置为并行垃圾回收线程数(ParallelGCThreads)的1/4左右。
            6. -XX: InitiatingHeap0ccupancyPercent设置触发并发GC周期的Java堆占用率阈值。超过此值,就触发GC。默认值是45。
          5. 操作步骤
            1. 开启G1垃圾收集器
            2. 设置堆的最大内存
            3. 设置最大停顿时间,即gc时用户所能容忍的工作任务因GC影响而停顿的时间。
          6. 回收模式
            1. YoungGC
            2. ConcurrentMarking
            3. MixedGC
            4. FullGC
          7. 使用场景
            1. 面向服务端,针对大内存,多处理的机器,普通大小的堆表现并暂时不如GMS
            2.  最主要的应用就是需要低GC延迟且具有大堆的应用程序提供解决方案。(堆在大于6G时会有好的效果)
            3. 使用G1要比GMS好的场景
              1. 超过50%的堆被活动数据占用
              2. 对象分配频率或年代提升频率变化很大
              3. GC停顿时间长
              4. HotSpot垃圾收集器里,G1是采用应用线程承担GC工作,而其他收集器是使用内置的JVM线程执行GC,当其他线程慢时,系统会调用G1来加速垃圾回收。
          8. Region介绍
            1. G1在使用时,它将整个堆划分为2048个大小相同且各自独立的Region块儿,每个块大小根据实际使用来定,可以手动设置,一般控制在1MB到32MB,且为2的N次幂。
            2. G1保留了新生代老年代的概念,但是不在物理隔离,通过Region动态分配实现逻辑连续。
            3. 除了原有的伊甸园区,年轻代,老年代,G1新增了一个H区,humongous,大对象区,如果对象大小超过了1.5个Region,就把该对象存到大对象区。
            4. 设置H的原因:对于堆中的大对象,默认会被直接分配到老年代,但是如果它是一个短期存在的大对象,就会对垃圾收集器造成负面影响。所以G1设置了一个H区,如果一个H区装不下,那就再寻找连续的H区存储,有时候为了能找到连续的H区,G1不得不启用FullGC。G1的大多数行为都把H区当做老年代看待。
          9. G1主要回收环节
            1. 年轻代的YoungGC
            2. 老年代的并发标记过程ConcurrentMarking
            3. 混合回收MixedGC
            4. 为了回收失败而存在的单线程独占高强度强制回收FullGC
          10. 详细步骤
            1. 年轻代的YoungGC(年轻代的垃圾回收只会回收伊甸园区和青年区)
              1. G1停止应用程序
              2. G1创建回收集,即需要被回收的内存分段集合,包括 伊甸园区和青年区
              3. 开启回收
                1. 扫描根,根指static变量指向的对象和正在执行的方法调用链条上的局部变量等。根引用连同RSet记录的外部引用作为扫描存活对象的入口
                2. 更新RSet,即刷新引用关系。
                3. 处理RSet,识别老年代对象指向的伊甸园区中的对象,这些对象被认为是存活对象。
                4. 复制对象,遍历对象树,伊甸园区中的对象会被复制到青年区,青年区对象年龄如果未达到阈值,则年龄加一,年龄达到阈值则复制进入老年带,如果伊甸园区的存活对象,青年区放不下,则直接晋升到老年代。
                5. 处理伊甸园区的软,弱,虚,引用。清空伊甸园区。
            2. 老年代的并发标记过程ConcurrentMarking
              1. 初始化标记:标记从根节点直接可达的对象,该阶段并发,触发一次 YoungGC。
              2. 根区域扫描:标记青年代中可直达老年代的被引用对象,在 YoungGC前完成。
              3. 并发标记:整个堆进行并发标记,期间如果发现标记区域的对象都是垃圾,则立即回收。同时并发标记过程中,会去计算每块区域的对象活性(区域中存活对象的比例)。
              4. 为防止标记出错,再进行一次基于快照算法( snapshot-at-the-beginning (SATB))的并行标记。
              5. 独占清理:并行计算各个区域对象的存活比例,进行排序,识别可以混合回收的区域,该阶段只是标记,并不清理。
              6. 并发清理:清理识别为完全空闲的区域。
            3. 混合回收: MixedGC混合回收是可以同时回收青年代和老年代的GC工具,除了回收全部青年代Region,还会回收部分老年代Region,
              1. 并发标记结束之后,老年代中百分百为垃圾的内存分段被回收了,部分为垃圾的内存分段被计算出来。默认这些老年代内存分段会被最多分8次回收,次数可以通过 -XX:G1MixedGccountTarget调节。
              2. 混合回收8分之一老年代内存分段,伊甸园区内存分段,青年代内存分段。
              3. G1会优先回收垃圾多的内存分段,垃圾占比越高,越先被回收。可以通过设置阈值( -XX:G1MixedGCLiveThresholdPercent,默认为65%)来决定。
              4. 混合回收不一定要8次,可设置阈值( -XX:G1HeapwastePercent,默认值为10%),意思是允许整个堆内存中有10%的空间被浪费,当发现可回收的垃圾低于10%则不再进行混合回收,因为GC花费的时间多,但是回收的内存少。
            4. FullGC,如果以上回收出现问题,不能工作,G1就会启动备用方案,全力回收内存。
      4. 总结
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值