想做网站制作运营注册什么公司核实,专业外贸网站制作价格,wordpress多用户多界面,网站安全建设需求文章目录 1 Java 垃圾回收1.1 JVM1.2 Java 对象生命周期 2 如何判断一个对象可被回收2.1 引用计数算法2.2 可达性分析算法 3 垃圾回收过程3.1 总体过程3.2 为什么要进行世代垃圾回收#xff1f;3.3 分代垃圾回收过程 在 C 和 C 中#xff0c;许多对象要求程序员声明他们后为其… 文章目录 1 Java 垃圾回收1.1 JVM1.2 Java 对象生命周期 2 如何判断一个对象可被回收2.1 引用计数算法2.2 可达性分析算法 3 垃圾回收过程3.1 总体过程3.2 为什么要进行世代垃圾回收3.3 分代垃圾回收过程 在 C 和 C 中许多对象要求程序员声明他们后为其分配资源然后才能安全地使用对象。使用完后则需要程序员将这些资源释放到自由内存池。如果资源得不到释放则认为代码泄露内存。然而如果过早地释放又可能发生数据丢失、Null指针等问题。
Java 和 C# 都有单独的管理应用程序管理对象的生存期并进行垃圾回收 (Garbage Collection - GC) 这样程序员可以不再关心内存释放问题保证系统的性能和稳定性。
这里记录 Java 垃圾回收相关知识点后面会再记录 C# 垃圾回收。 部分借鉴网络一些总结文章 1 Java 垃圾回收
Java 中JVM 通过跟踪已经分配资源的引用来释放不再使用的堆存。只要 JVM 检测到对象不再被引用垃圾回收器就会在适当的时候回收对象。
1.1 JVM
下载 Java 的时候我们会得到 JRE (Java Runtime Environment)JRE 中包括了 JVM (Java Virtual Machine) 和 类库 Java platform core classes Java platform libraries)。
Java 语言的一个重要特点就是与平台无关即得益于 JVM 的引入Java在不同平台上运行时不需要重新编译秩序生成在 JVM 上运行的目标代码就可以多平台运行。
JVM 定义了程序执行期间是用的数据区域如程序计数器、堆、栈、方法区、运行时常量池等。这些数据区域中的一些在JVM启动时创建JVM退出时销毁。
1.2 Java 对象生命周期
Java 中对象的生命周期包括
public class ObjectLifecycle {public static void main(String[] args) {ObjectLifecycle obj new ObjectLifecycle(); // 创建阶段// 使用阶段obj null; // 不可达阶段System.gc(); // 触发垃圾回收进入回收阶段}Overrideprotected void finalize() throws Throwable {super.finalize();System.out.println(垃圾回收前调用finalize方法);}
}2 如何判断一个对象可被回收
2.1 引用计数算法
给对象添加一个引用计数器对象每增加一个引用计数器加1引用失效计数器减1引用计数为0的对象可以被回收。
假如两个对象互相引用那么引用计数器永远不会为0导致对象无法回收因此 JVM 不再使用引用计数算法
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;}
}2.2 可达性分析算法
通过 GC Roots 作为起始点进行搜索所有不可达的对象即为可被回收的对象。 Java 虚拟机使用该算法来判断对象是否可被回收在 Java 中 GC Roots 一般包含以下内容:
在虚拟机栈(栈帧中的本地变量表)中引用的对象: Java public void method() { Object localVariable new Object(); // localVariable是GC Roots } 在方法区中类静态属性引用的对象: Java public class MyClass { private static Object staticObject new Object(); // staticObject是GC Roots } 在方法区中常量引用的对象: Java public class MyClass { private static final String CONSTANT_STRING “constant”; // CONSTANT_STRING是GC Roots } 在本地方法栈中JNI(即通常所说的Native方法)引用的对象: Java虚拟机内部的引用如基本数据类型对应的Class对象一些常驻的异常对象(比如NullPointExcepiton、OutOfMemoryError)等还有系统类加载器。 所有被同步锁(synchronized关键字)持有的对象: Javapublic synchronized void synchronizedMethod() { // 当前对象(this)在执行同步方法时是GC Roots } 所有被同步锁(synchronized关键字)持有的对象:
3 垃圾回收过程
3.1 总体过程
Step1. 标记 Marking GC 在这个阶段辨别内存是否被使用被引用的对象这里展示为蓝色没有被引用的为橙色。这个过程效率不高
Step2: 标准清理 Normal Deletion 清理时直接把可以回收的对象内存释放留下被引用的对象和指向可用空间的指针。内存碎片会导致没有足够连续的空间给大对象分配内存 Step3: 压缩清理 (Deletion with Compacting)
通过把被引用的对象都移动到一起后续为新对象分配内存则会更加容易和快速。
3.2 为什么要进行世代垃圾回收
如上所述标记和压缩 JVM 中所有对象是相当低效的随着分配的对象越来越多对象表越来越到导致垃圾回收时间越来越长。同时又有大量实证表明大多数对象生命都是短暂的。
下面是数据示例图Y周显示分配的字节数存活时间X是随着时间推移分配的字节数。
即随着时间推移分配的对象越来越少对。 因此从对象分配的行为中为了提高JVM 性能堆被分为了更小的部分或成为代分别是新生代(Young Gneration)、老年代 Old Generation 和 永久代Permanent Generation. 新生代新对象首先被分配到这里当年轻代内存用尽会触发一次 minor garbage colletion。如果对象的死亡率高那么这次 minor garbage collection 则会有效的优化内存。新生代会被分为一块较大的 Eden 空间和两块较小的 Survivor 空间每次使用一块 Eden 和一块 Survivor。回收时会将 Eden 和 Survivor 中还存活得对象复制到另一块 Survivor空间中最后清理 Eden 和使用过的那一块 Survivor。
这个过程会快速地完成当另一块 Survivor不足以存放 Eden 和 Survivor 存活对象时所有幸存对象 (surviving objects) 会被标记年龄并移动到 old generation。
Minor GC - Stop the world EventMinor GC 是 Stop the world 的行为即所有的应用县城都要停止直到整个操作完成。
老年代: 一般来说新生代对象的age达到一定的阈值就会被移动到老年代而老年代的回收称为 major garbage collection。
Major GC - Stop the world Event: Major GC 也是 Stop the world 的行为通常会更慢一些所以对于响应式应用程序应该尽量减少这类GC由于 Java 虚拟机提供了多种垃圾回收器这个GC的长度受垃圾回收器所影响。
永久代: 这里面包括了 JVM 描述应用进程中是用的类和方法所需要的静态文件。永久代也被称为方法区方法区的回收内容主要是 废弃常量和无用的类。
3.3 分代垃圾回收过程
上面我们理解了为什么要分代回收和回收的基本操作下面展示具体回收过程
1. 一个新的对象分配内存并记录在 Eden 区域 2. 当 Eden 区域占满触发一次 minor GC 3. 被引用对象移动到第一块 Survivor 区域S0没有被引用的对象则被删除 4. 在下一次 Minor GC类似上一步没有被引用的对象被释放Eden 和 引用对象则会被一起移动到第二块 Survivor 区域S1移动后Eden 和 S0 被清空可以看到现在 S1 区域有不同age的对象。
5. 下次 Minor GC同样的流程重复。但是这次 S0 和 S1 互换。引用的对象会被移动到 S0幸存的对象 age 继续增加Eden 和 S1 都被清空。 6. 经过几次 Minor GC 之后对象age达到阈值这里为8他们就会被移动到老年代 7.随着Minor GC 不停地进行幸存的对象持续promote到老年代 8. 随着老年代 的对象不断增多最终会触发 Major GC 来释放更多的内存空间。