做校园文化展览的网站,工业设计网站 知乎,wordpress搭建短视频网站,网页设计与制作的作用和意义目录
一、什么是垃圾回收#xff1f;
二、为什么要有垃圾回收机制#xff08;GC#xff09;#xff1f;
三、垃圾回收主要回收的内存区域
四、死亡对象的判断算法
a#xff09;引用计数算法
b#xff09;可达性分析算法
五、垃圾回收算法
a#xff09;标记-清除…目录
一、什么是垃圾回收
二、为什么要有垃圾回收机制GC
三、垃圾回收主要回收的内存区域
四、死亡对象的判断算法
a引用计数算法
b可达性分析算法
五、垃圾回收算法
a标记-清除算法
b复制算法
c标记-整理算法
d分代算法
六、垃圾回收器 一、什么是垃圾回收
垃圾回收指的是自动管理和释放不再被程序使用的内存资源的过程。在程序运行过程中动态分配的内存会被使用但也需要在不再需要时释放以免占用过多的内存空间导致内存泄漏或内存溢出等问题。
二、为什么要有垃圾回收机制GC
早在学习C语言中有这么一块内容动态内存管理。动态内存管理的主要内容就是通过 malloc 申请内存free 释放内存。
此处 malloc 申请到的内存生命周期是跟随整个进程的。这一点对于服务器程序就很不友好了服务器每个请求都去 malloc 一块内存如果没有 free 释放就会使申请的内存越来越多后续想要申请内存就无法申请了。这就是内存泄漏问题。
而在实际开发中很容易出现 free 不小心就忘记调用了或者因为一些情况导致 free 没有被执行到例如代码块中存在 if 导致的 return 或者 抛出异常了(当前C语言没有异常这一说)。因此内存泄漏是一个很大的问题。
能否让释放内存的操作由程序自动负责完成而不是依赖程序员手动释放呢
此时就引入了垃圾回收机制(GC)来解决上述问题。
三、垃圾回收主要回收的内存区域
JVM 在运行 Java 程序时将内存划分为不同的区域称为运行时数据区。这些区域包括方法区、堆、栈虚拟机栈、本地方法栈和程序计数器等。程序在执行之前先要把 Java 代码转换成字节码.class文件JVM 首先需要把字节码通过一定的方式类加载器把文件加载到内存中即运行时数据区。 对于程序计数器、虚拟机栈、本地方法栈这三部分区域而言其生命周期与相关线程有关随线程而生随线程而灭。并且这三个区域的内存分配与回收具有确定性因为当方法结束或者线程结束时内存就自然跟着线程回收了。
而对于方法区方法区主要存储的是类加载后的元数据信息静态变量常量池等这些信息在程序运行期间基本上是不会发生变化的。
因此在Java虚拟机中垃圾回收主要针对的是 堆 区域进行回收。
前面说到垃圾回收指的是自动管理和释放不再被程序使用的内存资源的过程在Java堆中存放着几乎所有的对象实例因此内存回收也可以叫做死亡对象的回收。
垃圾回收器在对堆进行垃圾回收前首先要判断这些对象哪些还存活哪些已经“死去”。判断对象是否已“死”有以下几种算法。
四、死亡对象的判断算法
a引用计数算法
引用计数法的描述如下
引用计数算法是一种简单的垃圾回收算法它基于对象的引用计数来确定何时可以回收对象。在引用计数算法中每个对象都会有一个与之关联的引用计数用来记录有多少个指针指向该对象。当引用计数为0时表示该对象不再被引用可以安全地回收。这种算法的实现相对简单通常在对象创建和销毁时维护引用计数。当有新的指针指向对象时引用计数加1当指针不再指向对象时引用计数减1。当引用计数减到0时垃圾回收器会立即回收该对象。
引用计数算法的优点是实现简单且判定效率也比较高可以及时回收不再使用的对象。比如Python语言就采用引用计数法进行管理内存。
但是在主流的JVM中没有选用引用计数法来管理内存最主要的原因就是引用计数法无法解决对象的循环引用问题。即如果两个或多个对象之间存在循环引用它们的引用计数永远不会为0即使它们已经不再被程序使用也无法被回收。这会导致内存泄漏占用大量的内存空间。
b可达性分析算法
JVM 就是采用“可达性分析”来判断对象是否存活同样采用此法的还有C#、Lisp该算法可以有效处理循环引用问题其核心思想为
通过一系列称为“GC Roots”的对象作为起始点从这些节点开始向下搜索遍历搜索走过的路径称之为“引用链”当一个对象到GC Roots没有任何的引用链相连时从GC Roots到这个对象不可达证明此对象是不可用的。一旦完成了可达性分析JVM 就可以安全地回收那些不可达的对象释放它们所占用的内存空间。 如上图所示对象Object5-Object7之间虽然彼此还有关联但是它们到GC Roots是不可达的因此它们会被判定为可回收对象。
★在Java语言中可作为GC Roots的对象包含下面几种
虚拟机栈栈帧中的本地变量表中引用的对象方法区中类静态属性引用的对象方法区中常量引用的对象本地方法栈中 JNI(Native方法)引用的对象。
通过可达性分析算法JVM 就能够将死亡对象标记出来了标记出来之后就要进行垃圾回收操作。在介绍垃圾回收器之前先介绍垃圾回收器使用的几种算法。
五、垃圾回收算法
a标记-清除算法
“标记-清除”算法是最基础的垃圾回收算法。算法分为“标记”和“清除”两个阶段首先标记出所有需要回收的对象在标记完成后统一回收所有被标记的对象。
后续的回收算法都是基于这种思路并对其不足加以改进而已。
“标记-清除”算法的不足主要有两个
效率问题标记和清除这两个过程的效率都不高特别是在堆中对象数量庞大的情况下。空间问题标记清除后会产生大量不连续的内存碎片内存碎片太多可能会导致以后在程序运行中需要分配较大对象时无法找到足够连续的内存而导致内存分配失败或不得不提前触发另一次垃圾回收。 b复制算法
“复制”算法解决了“标记-清除”算法两个主要问题即内存碎片化问题和效率问题。
它将可用内存按容量划分为大小相等的两块每次只使用其中的一块。当这块内存需要进行垃圾回收时会将此区域还存活着的对象复制到另一块上面然后再把已经使用过的内存区域一次清理掉。
这样做的好处就在于不仅解决了“标记-清除”的主要问题且算法实现简单运行高效。解决内存碎片化问题主要体现在复制过程中通过移动堆顶指针按顺序进行分配使碎片化内存被复制到连续的一块空间。
不过复制算法也有一些缺点例如在一轮GC中大部分对象都是长期存活的只有少数对象需要回收那么复制算法就会造成大量的复制操作导致影响性能。 c标记-整理算法
“标记-整理”算法的提出则是为了解决“复制”算法在对象存活率较高时会进行比较多的复制操作这样的问题。
标记过程仍与“标记-清除”算法的标记过程一致但后续步骤不是直接对可回收对象进行回收而是让所有存活对象都向一端移动以便整理出一块连续的内存空间。这个思想类似于双指针算法但其移动对象的过程更复杂。 上述过程仍有一些缺点即移动存活对象的过程会带来较大的开销。
d分代算法
综合以上三种算法JVM并没有直接使用其中的一种而是结合这三种算法搞出了一个“综合性”方案即分代算法。
实际上堆里面分为两个区域新生代和老生代新生代放新建的对象当经过一定 GC 次数之后还存活的对象才放入老生代。新生代还有三个区域一个 Endn 两个 SurvivorS0/S1. 分代算法就是通过区域划分实现不同区域使用不同的的垃圾回收策略从而实现更好的垃圾回收。
这就好比中国的一国两制方针一样对于不同的情况和地域设置更符合当地的规则从而实现更好的管理这就是分代算法的设计思想。
当前 JVM 垃圾回收都采用的是“分代”算法。在新生代中每次垃圾回收都有大批的对象死去只有少量存活因此采用复制算法而老年代中对象存活率高、没有额外空间对它进行分配担保就必须采用“标记-清除”或者“标记-整理”算法。 对于新生代来说98%的对象都是“朝生夕死”的所以并不需要按照11的比例来划分内存空间而是将新生代内存分为一块比较大的Eden(伊甸园)空间和两块比较小的Survivor(幸存者)空间每次使用Eden和其中一块Survivor两个Survivor区域一个称为From区一个称为To区。当回收时将Eden和Survivor中还存活的对象一次性复制到另一块Survivor上最后清理掉Eden和刚才使用过的Survivor空间。完成一次对象复制后From区和To区的角色会互换。HotSpot虚拟机默认Eden与Survivor的大小比例是81也就是说EdenSurvivor FromSurvivor To 811。所以每次新生代可用内存空间为整个新生代容量的90%而剩下的10%用来存放回收后存活的对象。 哪些对象会进入新生代哪些对象会进入老年代
新生代一般新创建的对象都会进入新生代老年代大对象和经历了 N 次一般情况默认是 15 次垃圾回收依然存活下来的对象会从新生代移动到老年代。
面试题请问了解 Minor GC 和 Full GC 吗这两种GC有什么不一样吗
Minor GC又称为新生代GC指的是发生在新生代的垃圾回收。因为新生代中的Java对象大多都具有朝生夕灭的特性因此Minor GC(采用复制算法)非常频繁一般回收速度也比较快。Full GC又称为老年代GC或者Major GC指发生在老年代的垃圾回收。出现了Major GC经常会伴随至少一次的Minor GC(并非绝对)。Major GC的触发频率通常比较低且速度一般会比Minor GC慢10倍以上。
六、垃圾回收器
如果说上面所讲的垃圾回收算法是内存回收的方法论那么垃圾回收器就是内存回收的具体实现。
垃圾回收器的作用垃圾回收器是为了保证程序能够正常、持久运行的一种技术它是将程序中的死亡对象也就是垃圾对象进行清除从而保证了新对象能够正常申请到内存空间。
以下这些回收器是 HotSpot 虚拟机随着不同版本推出的重要的垃圾回收器 上图展示了7种作用于不同分代的垃圾回收器如果两个回收器之间存在连线就说明它们之间可以搭配使用。所处的区域表示它是属于新生代回收器还是老年代回收器。
为什么会有这么多垃圾回收器
其主要原因是自从有了 Java 语言就有了垃圾回收器这么多垃圾回收器其实是历史发展的产物。随着时间的推移和技术的进步人们对垃圾回收器的性能、吞吐量、停顿时间等方面提出了更高的要求因此就产生了更多更新的垃圾回收器。
此处就不展开介绍每种垃圾回收器了。