zoukankan      html  css  js  c++  java
  • 垃圾回收

    GC Collector

    java vs c++

    java:自动处理

    • GC处理垃圾
    • 开发效率高,执行效率低
    java是有人帮你回收
    

    c++:手动处理,会有很多问题

    • 忘记回收,容易内存泄漏
    • 回收多次
    • 非法访问
    • 开发效率低,执行效率高
    c++比较精确,立马回收
    

    寻找垃圾的两种算法

    reference count

    1600589676870

    没有一根线连着它的时候,它就是垃圾
    

    Root Searching(根可达算法)

    1600590085064

    JAVA程序从main方法开始执行,,一个main方法会启动一个线程,这个线程里面会有线程栈,里面会有main栈帧。从这个main里面开始的这些对象都是我们的根对象,这个main方法调用了别的方法,那别的方法也是我们引用的,都是有用的对象,但是从main开始这个线程栈帧里面这些个叫做根对象,另外一个叫静态变量,一个class有一个静态的变量。load到内存后马上对静态变量进行初始化,所以静态变量访问的到的对象这个叫根对象。还有常量池指的是如果这个class会用到其他的class的那个类的对象,这些事根对象。JNI指的是如果你调用了c和c++写的那些本地方法所用到的那些个类或者对象。
    
    根可达算法:是从根上对象开始搜索
    线程栈变量:一个main方法开始运行,main线程栈中的变量调用了其他方法,main栈中的方法访问到的对象叫根对象
    静态变量:T.class对静态变量初始化能过访问到的对象叫做根对象
    常量池:如果一个class能够用到其他的class的对象叫做根对象
    JIN:如果调用的了本地方法运用到本地的对象叫做根对象
    

    根对象:当一个程序马上启动的时候需要的对象叫做根对象

    常见的垃圾回收算法

    • Mark-Sweep(标记清除)

      算法相对简单

      存活对象比较多的情况下效率较高

      Mark-Sweep:标记,清除。就是把它标记出来,然后清除。
      

      两遍扫描,效率偏低容易产生碎片

    • Copying(拷贝)

      适用于存活对象较少的情况

      只扫描一次,效率提高没有碎片


      空间浪费

      移动复制对象,需要调整对象引用

      Copying:就是把内存一分为二,分开之后把有用的拷贝到下面绿色区域,拷贝完后上面全部清掉。
      
    • Mark-Compact(标记压缩)

      不会产生碎片,方便对象分配

      不会产生内存减半

      Mark-Compact;就是把所有的东西整理的过程,清理的过程同时压缩到头上去。回收之前,有用的全往前面走,剩下的大块空间就全部清出来了。
      

      扫描两次

      需要移动对象,效率偏低

      堆内存逻辑分区

      这个分代算法和垃圾回收器是有关系的,分代这件事由于JVM分了这么多年,分代是存在于ZGC之前的所有垃圾回收器都是分代算法,除了G1之外的其他垃圾回收器不仅在逻辑上,在物理上也是分代的。

      1600653180914

    新生代分为:

    • eden(伊甸)默认比例8:是我们刚刚new出来对象之后往里扔的那块区域

    • survivor默认比例1:是回收一次之后跑到这个区域,这里面由于装的对象不同,所以采取的算法不同

    • survicor默认比例1:新生代存活对象特别少,死去对象特别多的算法是Copying

    • old老年代:

      • tenured(终身)

      老年代活着的对象特别多适用于:Mark Compact或Mark Sweep算法

    1600653696946

    这个对象到底是怎样进行GC过程的:一个对象产生后首先进行栈上分配,栈上如果分配不下会进入伊甸区,伊甸区经过一次垃圾回收之后进入survivor区,survivor区在经过一次垃圾回收之后又进入另一个survivor,与此同时伊甸区的某些对象也跟着进入另外一个survivor,什么时候年龄够了会进入old区,这是整个对象的一个逻辑上的移动过程。

    stack:s0-s1之间的复制年龄超过限制时,进入old区,通过参数:-XX:MaxTenuringThreshold配置。

    栈上分配

    • 线程私有小对象:小对象,线程是私有的
    • 无逃逸:就在某一段代码中使用,出了这段代码就没人认识它了
    • 支持标量替换:意思是用普通的属性、把普通的类型代替对象就叫标量替代
    • 无需调整

    栈上分配要比堆上分配要快,在站上分配不下,它会优先进行本地分配

    本地分配

    在伊甸区好多线程都往里头分配对象,分配对象的时候你这个线程一定会进行空间征用,谁抢到算谁的。多线程的同步效率就会低,所以设计了这么一个机制叫做TLAB

    • 占用eden,默认1%,在伊甸区取用百分之一的空间,这块空间叫做这个线程独有。分配对象的时候首先往我线程独有的这块空间里进行分配。
    • 多线程的时候不用争用eden就可以申请空间,提高效率
    • 小对象
    • 无需调整
    • 老年代
      • 大对象
    • eden
    java 回车//查看java参数
    
    • 横杠开头都是标志参数
    • -X是非标参数
    • -XX是不稳定参数
    • -Xms:起始的java堆大小
    • -Xmx:最大的java堆大小

    java的参数

    java -XX:printFlagsFinal -version//打印所有参数
    

    常见的垃圾回收器

    1601173495885

    JDK诞生之后第一个垃圾回收器就是Serial和Serial Old。

    常见的垃圾回收器组合有三种(Serial+Serial Old)、(Parallel Scavenge+Parallel Old)、(ParNew+CMS)

    Serial

    当工作的时候,所有工作线程全部停止,当工作的时候断开的线程则是垃圾,如果突然加入Serial则停止,进行清理垃圾。

    Serial Old

    这个用在老年代,他用的是mark-sweep的算法,用的也是单线程。

    Parallel Scavenge

    如果你在JVM没有做任何调优的话,默认的就是Parallel Scavenge和Parallel Old简称PS+PO。

    Parallel Old

    • a compacting collector that uses multiple GC threads
    • 整理算法

    ParNew

    和Parallel Scavenge没什么区别,就是做了一些增强,便于和CMS一起使用。

    CMS

    他回收垃圾的线程和工作线程同时进行,叫做concurrent mark sweep(concurrent 并发)。

    CMS产生的四个阶段

    • 初始标记STW开始的标记
    • 并发标记和应用程序同时运行
    • 重新标记又是一个STW,在并发标记中产生的新垃圾在重新标记中标记
    • 并发清理也会产生新的垃圾,叫做浮动垃圾
  • 相关阅读:
    透明度问题解决方案
    不得不去奋斗的原因
    未来的你肯定会感谢现在努力的你
    前端学习参考
    js仿京东轮播图效果
    hyper容器网络相关源码分析
    利用setns()将进程加入一个新的network namespace
    frakti && RunPodSandbox 源码分析
    Makefile 编写 tips
    《In Search of an Understandable Consensus Algorithm》翻译
  • 原文地址:https://www.cnblogs.com/striver20/p/13763536.html
Copyright © 2011-2022 走看看