人人设计网官方网站wordpress用oss图床

当前位置: 首页 > news >正文

人人设计网官方网站,wordpress用oss图床,二十四个关键词,电子商务网站有哪些功能图解 JVM 垃圾回收#xff08;一#xff09; 1.前言1.1 什么是垃圾1.2 内存溢出和内存泄漏 2.垃圾回收的定义与重要性3.GC 判断策略3.1 引用计数算法3.2 可达性分析算法 4.引用类型5.垃圾回收算法5.1 标记-复制#xff08;Copying#xff09;5.2 标记-清除#xff08;Mark… 图解 JVM 垃圾回收一 1.前言1.1 什么是垃圾1.2 内存溢出和内存泄漏 2.垃圾回收的定义与重要性3.GC 判断策略3.1 引用计数算法3.2 可达性分析算法 4.引用类型5.垃圾回收算法5.1 标记-复制Copying5.2 标记-清除Mark-Sweep5.3 标记-整理Mark-Compact5.4 分代收集理论5.5 垃圾回收阶段算法小结 1.前言 1.1 什么是垃圾 垃圾 是指运行程序中 没有任何引用指向的对象需要被回收。 1.2 内存溢出和内存泄漏 内存溢出经过垃圾回收之后内存仍旧无法存储新创建的对象内存不够溢出。 内存泄漏又叫 “存储泄漏”对象不会再被程序使用了但是 GC 又不能回收它们。例如IO 流不适用了但是没有被 Close、数据库连接 JDBC 没有被 Close。这些对象不会被回收就会占据内存大量的此类对象存在也是导致内存溢出的原因。 2.垃圾回收的定义与重要性 垃圾回收Garbage Collection简称 GC是内存管理的核心组成部分它负责自动回收不再使用的内存空间。在 Java 中程序员不需要手动释放对象占用的内存一旦对象不再被引用垃圾回收器就会在适当的时机回收它们所占用的内存。这样可以避免 内存泄漏 和 野指针从而大大减轻了程序员的负担也使得 Java 成为一个相对安全、易于开发的编程语言。 防止内存泄漏手动管理内存容易导致内存泄漏而 GC 可以自动回收不再使用的对象防止内存泄漏的发生。提高开发效率程序员不再需要关心内存释放的问题可以更加集中精力在业务逻辑的实现上。系统性能和稳定性通过有效的垃圾回收策略可以保证系统的性能和稳定性。 垃圾回收的基本步骤分两步 1️⃣ 查找内存中不再使用的对象GC 判断策略2️⃣ 释放这些对象占用的内存GC 收集算法 3.GC 判断策略 3.1 引用计数算法 给对象添加一个引用计数器当对象增加一个引用时计数器加 1引用失效时计数器减 1。引用计数为 0 的对象可被回收。两个对象出现循环引用的情况下此时引用计数器永远不为 0导致无法对它们进行回收。正因为循环引用的存在因此 Java 虚拟机不使用引用计数算法。 public class ReferenceCountingGC {public Object instance null;public static void main(String[] args) {ReferenceCountingGC objectA new ReferenceCountingGC();ReferenceCountingGC objectB new ReferenceCountingGC();objectA.instance objectB;objectB.instance objectA;} }3.2 可达性分析算法 通过 GC Roots 作为起始点进行搜索能够到达到的对象都是存活的不可达的对象可被回收。 哪些对象可以作为 GC Roots 呢 虚拟机栈栈帧中的局部变量表中引用的对象本地方法栈Native 方法中引用的对象方法区中类静态属性引用的对象方法区中常量引用的对象所有被同步锁持有的对象JNIJava Native Interface引用的对象 public void method() { Object localVariable new Object(); // localVariable 是 GC Roots }public class MyClass { private static Object staticObject new Object(); // staticObject 是 GC Roots }public class MyClass { private static final String CONSTANT_STRING constant; // CONSTANT_STRING 是 GC Roots }public synchronized void synchronizedMethod() { // 当前对象(this)在执行同步方法时是 GC Roots }4.引用类型 无论是通过引用计算算法判断对象的引用数量还是通过可达性分析算法判断对象是否可达判定对象是否可被回收都与引用有关。 Java 中有四种类型的引用它们对垃圾回收的影响不同 强引用Strong Reference最常见的引用类型只要对象有强引用指向它就不会被垃圾回收。软引用Soft Reference软引用可以帮助垃圾回收器回收内存只有在内存不足时软引用指向的对象才会被回收。弱引用Weak Reference弱引用指向的对象在下一次垃圾回收时会被回收不管内存是否足够。虚引用Phantom Reference虚引用的主要用途是跟踪对象被垃圾回收的状态虚引用指向的对象总是可以被垃圾回收。 import java.lang.ref.*;public class ReferenceTypes {public static void main(String[] args) {Object strongRef new Object(); // 强引用SoftReferenceObject softRef new SoftReference(new Object()); // 软引用WeakReferenceObject weakRef new WeakReference(new Object()); // 弱引用PhantomReferenceObject phantomRef new PhantomReference(new Object(), new ReferenceQueue()); // 虚引用System.gc(); // 触发垃圾回收System.out.println(Strong Reference: strongRef);System.out.println(Soft Reference: softRef.get());System.out.println(Weak Reference: weakRef.get());System.out.println(Phantom Reference: phantomRef.get());} }5.垃圾回收算法 5.1 标记-复制Copying 它可以将内存分为大小相同的两块每次使用其中的一块。当这一块的内存使用完后就将还存活的对象复制到另一块去然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收。 ✅ 优点: 减少内存碎片提高空间利用率。⭕ 缺点: 减半了可用的堆内存可能增加垃圾回收的频率。 5.2 标记-清除Mark-Sweep 算法分为“标记”和“清除”阶段 标记清除算法分为两个主要步骤标记 和 清除。 标记阶段: 在标记阶段垃圾回收器会从 GC Roots 开始遍历所有可达的对象并标记它们为活动对象。清除阶段: 在清除阶段垃圾回收器会遍历整个堆回收所有未被标记的对象的内存。 有两个明显的问题 效率问题如果需要标记的对象太多效率不高。空间问题标记清除后会产生大量不连续的内存碎片空间碎片太多可能会导致在运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集。 5.3 标记-整理Mark-Compact 标记整理算法是标记清除算法的改进版本。它在标记和清除的基础上增加了整理阶段将所有活动对象向一端移动从而消除内存碎片。 ✅ 优点: 解决了内存碎片化问题提高了空间利用率。⭕ 缺点: 移动对象增加了额外的开销。 5.4 分代收集理论 当前虚拟机的垃圾收集都采用分代收集算法根据对象存活周期的不同将内存分为几块。一般将 Java 堆分为新生代和老年代这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。 新生代Young Generation使用复制算法因为新生代中的对象生命周期较短。老年代Tenured Generation使用标记整理或标记清除算法因为老年代中的对象生命周期较长且数量较少。 1️⃣ 新生代的回收算法以 复制 算法为主 所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。新生代内存按照 8 : 1 : 1 8:1:1 8:1:1 的比例分为一个 eden 区和两个 survivorsurvivor0survivor1区一般而言。大部分对象在 eden 区中生成。回收时先将 eden 区存活对象复制到一个 survivor0 区然后清空 eden 区当这个 survivor0 区也存放满了时则将 eden 区和 survivor0 区存活对象复制到另一个 survivor1 区然后清空 eden 和这个 survivor0 区此时 survivor0 区是空的然后将 survivor0 区和 survivor1 区交换即保持 survivor1 区为空 如此往复。当 survivor1 区不足以存放 eden 和 survivor0 的存活对象时就将存活对象直接存放到老年代。若是老年代也满了就会触发一次 Full GCMajor GC也就是新生代、老年代都进行回收。新生代发生的 GC 也叫做 Minor GCMinor GC 发生频率比较高不一定等 eden 区满了才触发。 2️⃣ 老年代的回收算法以 标记-清除、标记-整理 为主 在年轻代中经历了N次垃圾回收后仍然存活的对象就会被放到老年代中。因此可以认为老年代中存放的都是一些生命周期较长的对象。内存比新生代也大很多大概比例是 1 : 2 1:2 1:2当老年代内存满时触发 Major GCMajor GC 发生频率比较低老年代对象存活时间比较长存活率标记高。 3️⃣ 永久代Permanet Generation的回收算法 JDK 1.8 及以后方法区的实现变成了元空间。 用于存放静态文件如Java类、方法等。永久代对垃圾回收没有显著影响但是有些应用可能动态生成或者调用一些 class例如 Hibernate 等在这种时候需要设置一个比较大的永久代空间来存放这些运行过程中新增的类。永久代也称 方法区。方法区主要回收的内容有废弃常量和无用的类。对于废弃常量也可通过根搜索算法来判断但是对于无用的类则需要同时满足下面 3 个条件 该类所有的实例都已经被回收也就是 Java 堆中不存在该类的任何实例。加载该类的 ClassLoader 已经被回收。该类对应的 java.lang.Class 对象没有在任何地方被引用无法在任何地方通过反射访问该类的方法。 5.5 垃圾回收阶段算法小结 标记复制标记清除标记压缩速率最快中最慢空间开销两个大小相同的空间少会堆积碎片少不会碎片堆积移动对象是否是