zoukankan      html  css  js  c++  java
  • Java的GC是什么?做了什么?

    Java GC是Java的垃圾回收机制

    • Java堆是被所有线程共享的一块内存区域,所有对象实例和数组都在堆上进行内存分配。为了高效的进行垃圾回收,虚拟机把堆内存分为新生代,老年代和永久代3个区域
    • 新生代可以分为Eden区和Survivor Space(S0,S1)区,大多数情况下,对象在Eden区分配,当Eden没有足够的内存空间时触发一次Minor GC
    • Survivor是幸存区,是新生代和老年代的缓冲区域,当新生代发生MinorGC时,会将存活的对象从Eden区移动到S0内存区域,并清空Eden区,当再次发生Minor GC时,将Eden和S0中存活的对象移到S1区;存活对象反复在S0和S1移动,当对象在Surivivor之间移动或者从Eden移动到Surivivor区时,对象的GC年龄会不断增加,当GC年龄超过默认阈值15会进入老年代
    • 老年代用于存放经过几次MinorGC后依然存活的对象,当老年代空间不足时会触发Full GC/Major GC,速度比MinorGC慢十多倍

    如何判断对象是否存活

    • 引用计数法

    对象上添加一个引用计数器,每当有一个对象引用它时,计数器加1,当使用完该计数器时,计数器减1,计数器为0表示该对象不被使用

    优点:实现简单,判定高效

    缺点:无法解决对象之间相互引用的问题

    • 可达分析法

    通过一系列的GC Roots对象作为起点,从这些起点开始向下搜索,搜索路径称为引用链

    可作为GC Roots的对象:

    1. 本地变量表中引用的对象 / 虚拟机栈中引用的对象
    2. 方法区中静态变量引用的对象
    3. 方法区中常量引用的对象
    4. Native方法引用的对象

    当一个对象到GCRoots没有任何引用链时,就表示该对象可以被回收

    使用可达性分析法判断一个对象是否可被回收需要经过两次标记:

    1. 对象ObjectA到GC Roots没有引用链,进行第一次标记
    2. 如果ObjectA重写了finalize方法,且还未执行过,那么ObjectA会被插入到一个F-Queue队列中,再由一个虚拟机自动创建的,低优先级的Finalizer线程触发其finalize方法。finalize方法中如果对象ObjectA与引用链中的对象建立联系,那么在进行第二次标记时ObjectA会被移出即将回收的集合(注:finalize方法只会被JVM调用一次)

    GC算法:

    • 标记清除(老年代)

    对待回收的对象进行标记

    缺点:标记和清除过程效率都很低,收集之后会留下很多内存碎片,不利于大对象的分配

    • 复制(年轻代)

    将内存分为大小相等的A和B两份,每次只使用一份,A中内存用完了,就把A中存活的对象复制到B中,并清空A的内存

    优点:只需要标记存活的对象,标记效率得到提高;避免了内存碎片的问题

    缺点:可用内存缩小为原来的一半

    • 标记整理(老年代)

    老年代中,对象的存活率较高,复制算法效率比较低,在标记整理算法中,标记出所有存活的对象并移到一端,然后直接清理边界以外的内存

  • 相关阅读:
    TCP源码—连接建立
    TCP系列02—连接管理—1、三次握手与四次挥手
    TCP系列01—概述及协议头格式
    ubuntu软件管理apt与dpkg
    318. Maximum Product of Word Lengths
    317. Shortest Distance from All Buildings
    316. Remove Duplicate Letters
    315. Count of Smaller Numbers After Self
    314. Binary Tree Vertical Order Traversal
    313. Super Ugly Number
  • 原文地址:https://www.cnblogs.com/qf123/p/8528147.html
Copyright © 2011-2022 走看看