0

0

在Java中对象生命周期如何理解_Java对象创建与回收解析

P粉602998670

P粉602998670

发布时间:2026-01-18 09:21:08

|

699人浏览过

|

来源于php中文网

原创

java对象生命周期取决于gc roots可达性而非创建或显式释放;对象真正创建需内存分配且构造方法执行完毕;未断开引用链(如静态集合、内部类、threadlocal)会导致延迟回收;finalize已废弃,应使用try-with-resources、cleaner或phantomreference。

在java中对象生命周期如何理解_java对象创建与回收解析

Java对象的生命周期不是“创建→使用→销毁”这么线性,关键在于引用关系是否还被GC Roots可达,而不是你有没有调用 new 或显式“释放”。对象真正进入可回收状态,往往比你想象中晚得多。

对象何时算“已创建”?不只是 new 完就完事

对象在堆上分配内存并完成初始化(即构造方法执行完毕)才算真正创建完成。但要注意:

  • new 表达式执行时,若堆空间不足且 GC 后仍无法满足,会直接抛出 OutOfMemoryError,此时对象根本没创建成功
  • 构造方法中若抛出异常(如 NullPointerException 或自定义异常),JVM 会回滚部分初始化:对象内存可能已分配,但引用不会赋值给变量,该对象立即成为垃圾
  • 使用 Unsafe.allocateInstance() 可绕过构造方法分配对象,此时对象处于“已分配但未初始化”状态——它 technically 存在,但字段全为默认值,且不推荐日常使用

为什么对象没被回收?先查引用链是否断开

GC 不看“你是不是不用了”,只看从 GC Roots(如帧中的局部变量、静态字段、JNI 引用等)出发能否找到该对象的引用路径。常见陷阱:

MindShow
MindShow

MindShow官网 | AI生成PPT,快速演示你的想法

下载
  • 静态集合类(如 static Map<string object> cache</string>)长期持有对象引用,即使业务逻辑早已弃用,对象也无法回收
  • 内部类默认持外部类强引用,若将非静态内部类实例注册为监听器或提交到线程池,容易导致外部对象内存泄漏
  • ThreadLocal 变量在线程结束前未调用 remove(),其 Entry 中的 value 会随线程存活而无法回收(尤其在线程池场景下)

finalize() 已废弃,替代方案是 Cleaner 或 PhantomReference

Object.finalize() 自 Java 9 起标记为 @Deprecated,Java 18 开始默认禁用,且行为不可靠(不保证执行、不保证及时、可能不执行)。正确做法:

立即学习Java免费学习笔记(深入)”;

  • 资源清理应通过 try-with-resources(实现 AutoCloseable)或显式 close() 完成
  • 若需在对象被回收时触发轻量级回调(如日志、统计),用 Cleaner
    Cleaner cleaner = Cleaner.create();
    cleaner.register(obj, new CleaningTask());
  • 需要更精细控制回收时机(比如等待对象不可达后做清理),可用 PhantomReference 配合 ReferenceQueue,但注意它无法获取原始对象,仅作通知用途

对象生命周期的复杂性,主要藏在引用关系的隐式维持里——一个没清空的 WeakHashMap 的 key、一个忘了 unregister 的观察者、甚至一个未关闭的 Stream,都可能让本该回收的对象多活几轮 GC。别依赖 finalize,也别假设“没用了就自动没了”。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1010

2023.08.02

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

443

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

605

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

443

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

605

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

764

2023.08.10

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

77

2025.09.05

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

40

2025.11.16

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

4

2026.03.10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.3万人学习

C# 教程
C# 教程

共94课时 | 11.1万人学习

Java 教程
Java 教程

共578课时 | 80.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号