需要回收的位置如下
其实垃圾回收是jvm自带的功能,所以有了如下的优缺点
优点:
1.项目开发的时候不需要开发人员考虑内存管理
2.可以有效的防止内存泄漏,更加高效的利用可使用的内存
3.因为垃圾回收不再有了作用于的概念
缺点:
因为不了解所以使用过程中会出现内存溢出和内存泄漏的问题
下面将判断对象存活的算法进行简单说明
引用计数算法:它的意思就是给每个创建的对象添加一个引用计数器,被引用计数值加1,引用失效时减一,当计数值为0时,表示该对象就不再被使用了
优点:
实现简单,执行效率高
缺点:
检测不到循环引用
实际案例
因为引用一直存在了,永远无法进行回收了,请注意java中的垃圾回收并没有使用引用计算算法
可达性分析算法:官方解释是通过一系列GC ROOTs 对象作为起始点,从起点开始向下搜索对象的路径,搜索所经过的路径称为引用链,当一个对象和任何一个GC ROOTs都没有引用链时,最终判断该对象不可用
先看图
再看下可以作为GC Roots的对象有哪些
1.栈帧中的局部变量表中的reference引用所引用的对象
2.方法区中static静态引用的对象
3.方法区中final常量引用的对象
4.本地方法栈中JNI(Native方法)引用的对象
5.Java虚拟机内部的引用, 如基本数据类型对应的Class对象, 一些常驻的异常对象(比如 NullPointExcepiton、
6.OutOfMemoryError) 等, 还有系统类加载器。
7.所有被同步锁(synchronized关键字) 持有的对象
8.反映Java虚拟机内部情况的JMXBean、 JVMTI中注册的回调、 本地代码缓存等
这里可达性分析算法是java判断对象存活使用的
但是这个时候的对象还并不能进入死亡,还需要再次的判断
下面通过模拟的程序进行说明
代码部分
package com.java.test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.ref.PhantomReference; import java.lang.ref.WeakReference; /** * @Description: * @Author: qiuxie * @Create: 2023/6/2 14:18 */ public class FinalizeEscapeGc { /** * 定义日志对象 */ private static final Logger logger= LoggerFactory.getLogger(FinalizeEscapeGc.class); public static FinalizeEscapeGc SAVE_HOOK=null; public void isAlive(){ logger.info("是的,我仍然活着"); } @Override protected void finalize() throws Throwable { super.finalize(); logger.info("finalize 方法执行中"); FinalizeEscapeGc.SAVE_HOOK=this; } public static void main(String[] args) { SAVE_HOOK=new FinalizeEscapeGc(); logger.info("打印SAVE_HOOK:{}",SAVE_HOOK); //开始第一次的自救 SAVE_HOOK=null; System.gc(); //因为finalize()优先级比较低,设置等待0.5秒 try { Thread.sleep(500); if (SAVE_HOOK!=null){ logger.info("开始第一次判断是否存活"); SAVE_HOOK.isAlive(); }else { logger.info("第一次的自救 很抱歉,我已经死亡了"); } } catch (InterruptedException e) { logger.error("睡眠异常:{}",e); } logger.info("第二次自救前 打印SAVE_HOOK:{}",SAVE_HOOK); //只能救一次,第二次自救会失败 //开始第二次的自救 SAVE_HOOK=null; System.gc(); //因为finalize()优先级比较低,设置等待0.5秒 try { Thread.sleep(500); if (SAVE_HOOK!=null){ logger.info("开始第二次判断是否存活"); SAVE_HOOK.isAlive(); }else { logger.info("第二次的自救 很抱歉,我已经死亡了"); } } catch (InterruptedException e) { logger.error("睡眠异常:{}",e); } logger.info("最后打印SAVE_HOOK:{}",SAVE_HOOK); } }
pom依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
这个org.slf4j已经被包含在springboot了
下面给出两次标记的走向图
注意点:finalize()执行缓慢,会有发生死循环的可能性,甚至最终导致内存回收子系统的崩溃
标签:info,HOOK,对象,存活,算法,引用,logger,SAVE From: https://www.cnblogs.com/q202105271618/p/17445506.html