延吉网站开发公司软件开发系统设计
- 作者: 五速梦信息网
- 时间: 2026年03月21日 07:03
当前位置: 首页 > news >正文
延吉网站开发公司,软件开发系统设计,网站开发实战演练,中国智慧城市建设门户网站开始之前有几个GC的基本问题 什么是GC#xff1f; GC 是 garbage collection 的缩写#xff0c;意思是垃圾回收——把内存#xff08;特别是堆内存#xff09;中不再使用的空间释放掉#xff1b;清理不再使用的对象。 为什么要GC#xff1f; 堆内存是各个线程共享的空间…
开始之前有几个GC的基本问题 什么是GC GC 是 garbage collection 的缩写意思是垃圾回收——把内存特别是堆内存中不再使用的空间释放掉清理不再使用的对象。 为什么要GC 堆内存是各个线程共享的空间不能无节制的使用。服务器运行的时间通常都很长。累积的对象也会非常多。这些对象如果不做任何清理任由它们数量不断累加内存很快就会耗尽。所以GC就是要把不使用的对象都清理掉把内存空间空出来让项目可以持续运行下去。 什么样的对象是垃圾对象 不再使用或获取不到的对象是垃圾对象。 如何把垃圾对象找出来 办法1引用计数法不采用不能解决循环引用问题 办法2可达性分析从GC Roots对象出发不可达的对象就是要清理的对象 找到垃圾对象如何执行清理 具体的GC算法
为什么要有垃圾回收
线程私有空间无需由系统来执行GC。因为线程结束释放自己刚才使用的空间即可不影响其它线程。线程共享空间任何一个线程结束时都无法确定刚才使用的空间是不是还有别的线程在使用。所以不能因为线程结束而释放空间必须在系统层面统一垃圾回收。
GC的基本原则
频繁收集新生代较少收集老年代基本不动元空间
如何确定垃圾
想要回收垃圾必须得先知道哪些对象可以被认定为垃圾。关于垃圾确定方式主要有两种分别是引用计数法与可达性分析法其原理分别如下
引用计数法不采用
工作机制 引用计数法是在对象每一次被引用时都给这个对象专属的『引用计数器』1。当前引用被取消时就给这个『引用计数器』-1。当前『引用计数器』为零时表示这个对象不再被引用了需要让GC回收。可是当对象之间存在交叉引用的时候对象即使处于应该被回收的状态也没法让『引用计数器』归零。 Member member01 new Member();Member member02 new Member();member01.setFriend(member02);member02.setFriend(member01);member01 null;member02 null;引用计数法的关键问题该清理的对象清理不掉。
简单的说就是在 Java 中引用与对象相关联如果要操作对象则必须使用引用。因此可以通过引用计数来确定对象是否可以回收。实现原则是如果一个对象被引用一次计数器 1反之亦然。当计数器为 0 时该对象不被引用则该对象被视为垃圾并且可以被 GC 回收利用。
SpringMVC 组件
IOC 容器对象的接口类型WebApplicationContext WebApplicationContext 对象初始化过程中将它自己存入 ServletContext 域WebApplicationContext 对象也会把 ServletContext 存入 IOC 容器Servlet 上下文对象ServletContext 可达性分析法
核心原理判断一个对象是否存在从『堆外』到『堆内』的引用。
为了解决引用计数法的循环引用问题Java 采用了可达性分析的方法。其实现原理是将一系列GCroot对象作为搜索起点。如果在GCroot和一个对象之间没有可达的路径则该对象被认为是不可访问的。 要注意的是不可达对象不等价于可回收对象不可达对象变为可回收对象至少要经过两次标记过程。两次标记后仍然是可回收对象则将面临回收。
垃圾回收算法
了解了垃圾的确定方法后我们将继续了解垃圾是怎么被回收的即垃圾回收算法。在Java中主要有四中垃圾回收算法分别是标记清除算法、复制算法、标记整理算法 和 分代收集算法。
基本算法引用计数法不推荐
引用计数算法很简单它实际上是通过在对象头中分配一个空间来保存该对象被引用的次数。如果该对象被其它对象引用则它的引用计数加一如果删除对该对象的引用那么它的引用计数就减一当该对象的引用计数为0时那么该对象就会被回收。
引用计数垃圾收集机制它只是在引用计数变化为0时即刻发生而且只针对某一个对象以及它所依赖的其它对象。所以我们一般也称呼引用计数垃圾收集为直接的垃圾收集机制。垃圾收集的开销被分摊到整个应用程序的运行当中了而不是在进行垃圾收集时要挂起整个应用的运行直到对堆中所有对象的处理都结束。因此采用引用计数的垃圾收集不属于严格意义上的Stop-The-World的垃圾收集机制。 优点 实时性较高不需要等到内存不够时才回收垃圾回收时不用挂起整个程序不影响程序正常运行 缺点 回收时不移动对象, 所以会造成内存碎片问题不能解决对象间的循环引用问题 标记清除算法
“标记-清除”算法是最基础的算法它的做法是当堆中的有效内存空间被耗尽的时候就会暂停、挂起整个程序也被称为stop the world然后进行两项工作第一项则是标记第二项则是清除。 标记标记的过程其实就是从根对象开始遍历所有的对象然后将所有存活的对象标记为可达的对象。 清除清除的过程将遍历堆中所有的对象将没有标记的对象全部清除掉。 优点实现简单 缺点 效率低因为标记和清除两个动作都要遍历所有的对象垃圾收集后有可能会造成大量的内存碎片垃圾回收时会造成应用程序暂停 由标记清除算法的实现我们可以看出其主要存在两个缺点 效率问题。标记和清除过程的效率都不高空间问题。标记清除之后会产生大量不连续的内存碎片空间碎片太多可能会导致当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作 复制算法
为了解决标记清除算法内存碎片化严重的缺陷提出了复制算法。复制算法主要思想是按内存容量将内存划分为大小相等的两块区域。每次只使用其中一块当这一块内存满后将其中存活的对象复制到另一块上去然后把该内存中的垃圾对象清理掉其实现过程如图 优点1在垃圾多的情况下(新生代)效率较高 优点2清理后内存无碎片 缺点浪费了一半的内存空间在存活对象较多的情况下(老年代)效率较差 复制算法虽然实现简单内存效率高不易产生碎片但是最大的问题是可用内存被压缩到了原本的一半。且存活对象增多的话Copying 算法的效率会大大降低。
标记整理算法
结合了以上两个算法为了避免缺陷而提出。标记阶段和标记清理算法相同标记后不是清理对象而是将存活对象移向内存的一端。然后清除端边界外的对象。如图 分代收集算法
在结合以上三种算法的综合分析及 JVM 内存对象生命周期的特点诞生了一种新的垃圾回收算法——分代收集算法。其核心思想是根据对象存活的不同生命周期将内存划分为不同的域一般情况下将 GC 堆划分为老年代(Tenured/Old Generation)和新生代(Young Generation)。老年代的特点是每次垃圾回收时只有少量对象需要被回收新生代的特点是每次垃圾回收时都有大量垃圾需要被回收因此可以根据不同区域选择不同的算法。
分代算法其实就是这样的根据回收对象的特点进行选择。
新生代适合使用复制算法老年代适合使用标记清除或标记压缩算法
垃圾回收器
串行垃圾回收器
串行在一个线程内执行垃圾回收操作。
新生代串行回收器 SerialGC采用复制算法实现单线程垃圾回收独占式垃圾回收器老年代串行回收器 SerialOldGC采用标记压缩算法单线程独占式垃圾回收器
并行垃圾回收器
并行在多个线程中执行垃圾回收操作。
新生代 ParNew 回收器采用复制算法实现多线程回收器独占式垃圾回收器。新生代 ParallelScavengeGC 回收器采用复制算法多线程独占式回收器老年代 ParallelOldGC 回收器: 采用标记压缩算法多线程独占式回收器 CMS回收器 CMS全称 (Concurrent Mark Sweep)是一款并发的、使用标记-清除算法的垃圾回收器。对CPU资源非常敏感。 启用CMS回收器参数 -XX:UseConcMarkSweepGC。 使用场景GC过程短暂停顿适合对时延要求较高的服务用户线程不允许长时间的停顿。 优点最短回收停顿时间为目标的收集器。并发收集低停顿。 缺点服务长时间运行造成严重的内存碎片化。算法实现比较复杂。 G1回收器 G1(Garbage-First)是一款面向服务端应用的并发垃圾回收器, 主要目标用于配备多颗CPU的服务器治理大内存。是JDK1.7提供的一个新收集器是当今收集器技术发展的最前沿成果之一。 G1计划是并发标记-清除收集器的长期替代品。 启用G1收集器参数-XX:UseG1GC启用G1收集器。 G1将整个Java堆划分为多个大小相等的独立区域(Region)虽然还保留有新生代和老年代的概念但新生代和老年代不再是物理隔离的了, 它们都是一部分Region(不需要连续)的集合。 每块区域既有可能属于Old区、也有可能是Young区因此不需要一次就对整个老年代/新生代回收。而是当线程并发寻找可回收的对象时有些区块包含可回收的对象要比其他区块多很多。虽然在清理这些区块时G1仍然需要暂停应用线程但可以用相对较少的时间优先回收垃圾较多的Region(这也是G1命名的来源)。这种方式保证了G1可以在有限的时间内获取尽可能高的收集效率。 特点 一整块堆内存被分成多个独立的区域Regions 存活对象被拷贝到新的Survivor区 新生代内存由一组不连续的堆heap区组成使得可以动态调整各个区域 多线程并发GC young GC会有STWStop the world事件
垃圾回收器对比
新生代回收器
名称串行/并行/并发回收算法适用场景可以与CMS配合SerialGC串行复制单CPU是ParNewGC并行复制多CPU是ParallelScavengeGC并行复制多CPU且关注吞吐量否
老年代回收器
名称串行/并行/并发回收算法适用场景SerialOldGC串行标记压缩单CPUParNewOldGC并行标记压缩多CPUCMS并发几乎不会暂停用户线程标记清除多CPU且与用户线程共存
finalize 机制
总体机制介绍
java.lang.Object 类中有一个方法
protected void finalize() throws Throwable { }方法体内是空的说明如果子类不重写这个方法那么不执行任何逻辑。 在执行 GC 操作前调用 finalize() 方法的是 Finalizer 线程这个线程优先级很低。在对象的整个生命周期过程中finalize() 方法只会被调用一次。
代码验证
public class FinalizeTest {// 静态变量public static FinalizeTest testObj;Overrideprotected void finalize() throws Throwable {// 重写 finalize() 方法System.out.println(Thread.currentThread().getName() is working);// 给待回收的对象this重新建立引用testObj this;}public static void main(String[] args) {// 1、创建 FinalizeTest 对象FinalizeTest testObj new FinalizeTest();// 2、取消引用testObj null;// 3、执行 GC 操作System.gc();// ※ 让主线程等待一会儿以便调用 finalize() 的线程能够执行try { TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {}// 4、判断待回收的对象是否存在if (FinalizeTest.testObj null) {System.out.println(待回收的对象没有获救还是要被 GC 清理);} else {System.out.println(待回收的对象被成功解救);}// 5、再次取消引用FinalizeTest.testObj null;// 6、再次执行 GC 操作System.gc();// 7、判断待回收的对象是否存在if (FinalizeTest.testObj null) {System.out.println(待回收的对象没有获救还是要被 GC 清理);} else {System.out.println(待回收的对象被成功解救);}}}执行效果 Finalizer is working 待回收的对象被成功解救 待回收的对象没有获救还是要被 GC 清理
- 上一篇: 延吉网站建设多少钱商丘房产网
- 下一篇: 延平网站建设wzjseotradekey外贸平台官网
相关文章
-
延吉网站建设多少钱商丘房产网
延吉网站建设多少钱商丘房产网
- 技术栈
- 2026年03月21日
-
延边网站建设公司wordpress 多语言版本
延边网站建设公司wordpress 多语言版本
- 技术栈
- 2026年03月21日
-
延安网站建设费用教做黏土手工的网站
延安网站建设费用教做黏土手工的网站
- 技术栈
- 2026年03月21日
-
延平网站建设wzjseotradekey外贸平台官网
延平网站建设wzjseotradekey外贸平台官网
- 技术栈
- 2026年03月21日
-
严什么的烟 网站建设上海网站制作与推广
严什么的烟 网站建设上海网站制作与推广
- 技术栈
- 2026年03月21日
-
研究生核心课程建设网站什么软件做美食视频网站
研究生核心课程建设网站什么软件做美食视频网站
- 技术栈
- 2026年03月21日
