图文深入理解java对象从创建到回收都经历了什么

1. 前言:

每个java对象都是有生命周期的,就像一个人的生命一样,从孕育到出生到成长变老最后由归于自然。笔者认为,Java对象的整个生命周期可以分为两个大的阶段:即创建阶段和运行阶段(包含对象的回收和消亡)。本篇将会图文深入介绍java对象的整个生命过程。
一般人平时看到java其实只是冰山的一角–java世界的冰上部分,冰下的java世界其实更精彩。
在这里插入图片描述

1.java对象的创建阶段

在Java中,对象的创建是一个复杂但有序的过程,涉及多个步骤和底层的JVM(Java虚拟机)运作。java对象的创建过程近似于下图,详细过程如下:
在这里插入图片描述

1. 类的加载

其实,在创建对象之前,JVM需要确保类已经被加载、链接和初始化,但这个过程属于对象的孕育阶段,就像一个人在母体一样,所以也是算作对象的创建阶段:

  1. 加载(Loading):将类的字节码从文件系统中读取到内存中。
  2. 链接(Linking),又可分为三个阶段:
    验证(Verification):确保字节码是合法的,不会违反Java语言的语义规则。
    准备(Preparation):为类的静态变量分配内存并设置为默认值(例如,int为0,引用类型为null)。
    解析(Resolution):将符号引用转换为直接引用(例如,将方法名转换为方法地址)。
  3. 初始化(Initialization):执行类的初始化代码,包括静态变量的赋值和静态块的执行。

2. 分配内存

在这里插入图片描述

在类加载完成后,JVM会在堆内存中为对象分配空间。实际运作过程如下:

  1. 判断是否需要线程安全:如果多个线程同时创建同一个类的对象,JVM需要确保内存分配的原子性。这可以通过两种方式实现:
  2. 使用同步机制:确保每次只有一个线程可以分配内存。
  3. 使用本地线程分配缓冲区(TLAB,Thread Local Allocation Buffers):每个线程在堆内存中预先分配一块私有空间,用于对象的分配。这样可以减少同步的开销。
  4. 分配内存:在堆中分配内存空间,具体方式取决于JVM使用的垃圾回收器。例如,在使用Serial GC时,直接分配在Eden区;在使用G1 GC时,根据对象的预期存活时间选择适当的区域。

3. 初始化内存

分配的内存空间初始化为零(基本数据类型,对象引用类型初始化为null)。这一步确保了对象的字段在构造方法执行之前处于确定的状态。

4. 设置对象头

每个对象在内存中都有一个对象头(Object Header),用于存储对象的一些元数据,包括:
哈希码(Hash Code):用于快速查找对象,例如在HashMap中。
GC分代年龄(GC Age):记录对象在垃圾回收过程中经过的次数,用于决定对象是否晋升到老年代。
锁状态标志(Lock Status):记录对象是否被锁定,以及锁的类型(轻量级锁、重量级锁等)。
类元数据指针(Class Metadata Pointer):指向对象的类元数据,用于在运行时访问类信息。

5. 执行构造方法

在对象内存分配和初始化之后,JVM会调用对象的构造方法来完成对象的初始化。构造方法中的代码会设置对象的字段值并执行其他初始化逻辑。

6. 返回引用

构造方法执行完毕后,JVM会将新创建对象的引用返回给调用者。此时,对象已经完全创建并可以使用了。

java对象的运行阶段

在这里插入图片描述

  1. 对象的使用(Usage)
    一旦对象被创建并初始化,它就可以被应用程序使用。对象通过其引用变量进行访问和操作。演示如下:
public class Person {  static String period = "GESTATION";  int instanceVar;  static {  // 静态初始化块  System.out.println("这是我的孕育阶段");  }  public void say() {  System.out.println("我就是我,不一样的烟火!");  }  public Person() {  // 构造函数  System.out.println("构造函数被执行");  this.instanceVar = 0;  }  public static void main(String[] args) {  Person person = new Person();  System.out.println("我出生了");  // 可以调用person的say方法  person.say();  }  
}
  1. 对象的垃圾回收(Garbage Collection)
    当对象不再被应用程序使用时,JVM的垃圾回收器(Garbage Collector, GC)会自动回收该对象所占用的内存空间。Java使用自动垃圾回收机制,程序员不需要手动释放内存。垃圾回收的判断依据主要是对象的可达性(Reachability),即对象是否从根集合(Root Set)可达。常见的可达性状态包括:
    可达(Reachable):对象可以从根集合直接或通过其他可达对象间接到达。
    可复活(Resurrectable):对象的所有引用都被释放,但在某个时间点它可能再次变为可达。
    不可达(Unreachable):对象既不是可达的,也不是可复活的。这些对象会被垃圾回收器回收。
  2. 对象的终结(Finalization)
    Java提供了一个finalize()方法,允许对象在垃圾回收之前执行清理操作。然而,需要注意的是,finalize()方法并不保证会被及时调用,也不应该被用作主要的清理机制。从Java 9开始,finalize()方法已被弃用,建议使用java.lang.ref.Cleaner和java.lang.ref.PhantomReference来替代。
  3. 对象的销毁(Destruction)
    对象的销毁是指对象所占用的内存空间被垃圾回收器回收的过程。在Java中,对象的销毁是自动进行的,程序员无法直接控制。

本篇完结。
码字不易,宝贵经验分享不易,请各位支持原创,转载注明出处,多多关注作者,家人们的点赞和关注是我笔耕不辍的动力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/446993.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LSTM时序预测 | Python实现LSTM长短期记忆神经网络时间序列预测

本文内容:Python实现LSTM长短期记忆神经网络时间序列预测,使用的数据集为AirPassengers 目录 数据集简介 1.步骤一 2.步骤二 3.步骤三 4.步骤四 数据集简介 AirPassengers 数据集的来源可以追溯到经典的统计和时间序列分析文献。原始数据集由 Box,…

一个好的维权小程序应该是什么样的?

小程序如今为大家提供了很多的便利服务,且小程序的种类、功能是很多样的,那么对于一个好的维权小程序来说,其功能和设计应该紧紧围绕着用户的需求。 设计页面应该直观简单,功能布局让人一目了然;操作简单,…

外包干了30天,技术明显退步:一段自我觉醒与转变的旅程

在人生的长河中,每个人都会遇到属于自己的转折点。我也不例外。作为一个本科生,我于2019年通过校招踏入了南京某软件公司的大门,成为了一名功能测试工程师。在那个相对安逸的环境中,我度过了将近两年的时光。然而,随着…

当下的时代?

我这两天刚接触一个人,错误之皇,每做一件小事的时候他都像救命稻草一样抓着,有一天我一看,嚯,好家伙,他抱着的是已经让我仰望的参天大树了! 这个时代需要我们从无限思维的视角和做法去努力;它不取决于我们现在有多少,而取决于我们未来的成长幅度是多少&a…

Dev-C++萌新学习福利3

朝鲜球作品原创https://blog.csdn.net/2401_86502594?spm1011.2124.3001.5343 清北互联地址https://www.17ac.cn/#/ 萌新福利 作品成本6999元!!! 清北互联团队编写课程,本人不收费。亏本买卖,良心服务,同嫂…

IP地址类型选择指南:动态IP、静态IP还是数据中心IP?

你是否曾经困惑于如何选择最适合业务需求的IP地址类型?面对动态IP、静态IP和数据中心IP这三种选择,你是否了解它们各自对你的跨境在线业务可能产生的深远影响? 在跨境电商领域,选择合适的IP类型对于业务的成功至关重要。动态IP、…

技术分享 —— JMeter接口与性能测试实战!

前言 在软件开发和运维过程中,接口性能测试是一项至关重要的工作。JMeter作为一款开源的Java应用,被广泛用于进行各种性能测试,包括接口性能测试。本文将详细介绍如何使用JMeter进行接口性能测试的过程和步骤。 JMeter是Apache组织开发的基…

JavaSE--全盘拿下数组的关键要领

嗨嗨大家~我来啦!今天我们来进入数组的学习吧。 目录 一 数组的定义 1 创建数组 2 初始化数组 二 数组的使用 1 数组的访问 2 数组的遍历 2.1 for 循环打印 2.2 for-each 打印数组 三 数组是引用类型 3.1 JVM内存分布 3.2 区分基本类型与引用类型变…

Taro 中 echarts 图表使用

1 下载 echarts4taro3 yarn add echarts4taro3 或 pnpm add echarts4taro3 或 npm i echarts4taro3 --save2 图表初始化需要先加载echarts模块 import * as echarts from "echarts4taro3/lib/assets/echarts"; // 这里用了内置的,也可以用自定义的 echa…

TCP与UDP协议(三次握手四次挥手)

TCP与UDP 简介TCP和UDP一、TCP1.1 TCP的三次握手问题来了:为啥是三次握手而不是两次呢? 1.2建立连接后的通信过程(丢包与乱序问题)1.3四次挥手问题来了:为什么要四次挥手? 二、UDP 简介TCP和UDP TCP、UDP都…

SQL第16课——更新和删除数据

介绍如何利用update和delete语句进一步操作表数据。 16.1 更新数据 使用update语句。两种使用方式: 1. 更新表中的特定行; 2. 更新表中的所有行。 !!!(使用update时不要省略where子句,因为…

链接伪类(:hover)CSS背景图片有闪动BUG的解决方法 vue3

现象: hover时候,图片还没加载出来,导致边框闪烁 在Vue 3中,如果你遇到了使用伪类(:hover)时背景图片出现闪烁的问题,可能是由于浏览器的渲染机制导致的。解决这个问题的方法可能包括: 使用background-pos…

spark:数据的关联与合并、缓存和checkpoint

文章目录 1. 数据的关联与合并1.1 join关联1.1.1 内关联1.1.2 左关联1.1.3 右关联 1.2 Union合并 2. 缓存和checkpoint 1. 数据的关联与合并 1.1 join关联 students表数据: 1.1.1 内关联 内关联只返回两个 DataFrame 中在连接键上匹配的行。 # join 关联 from…

【Linux】【Jenkins】后端项目打包教程-Linux版

本次安装版本:2.4 1、安装git环境2、安装mavne环境2.1 下载依赖2.2、解压、赋权2.2、配置环境变量2.3、验证安装 3、jenkins-插件下载3.1、进入jenkins-->系统管理3.2、进入系统管理-->插件管理3.3、下载两个插件(如果之前下载了,这里是…

Docker 的使用-01

一、Docker 设置和镜像源 1.1、设置 #查看 Docker 信息 docker version docker info#守护线程启动: systemctl daemon-reload 重启Docker服务: systemctl restart docker#关闭Docker服务 sudo systemctl stop docker#启动Docker服务 systemctl start d…

【安装JDK和Android SDK】

安装JDK和Android SDK 1 前言2 下载2.1 下载途径2.2 JDK下载和安装2.2.1 下载2.2.2 安装并配置环境变量2.2.3 验证 2.3 SDK下载和安装2.3.1 下载2.3.2 安装2.3.3 环境变量配置2.3.4 验证 1 前言 在软件开发中,Android应用开发通常使用Android Studio,但…

低成本轻量化5G网络部署redcap技术

RedCap(Reduced Capability)轻量化5G路由器旨在提供低功耗、成本效益高、性能较5G完整版稍微降低的解决方案。用于满足工业物联网(IoT)、消费电子产品和轻量级5G设备的需求。通过对5G技术进行一定程度的“功能裁剪”,降…

【华为】配置RIP协议

RIP(Routing Information Protocol)是一种内部网关协议(IGP),主要用于小型网络中的动态路由。RIP有两个主要版本:‌RIPv1和‌RIPv2,它们之间存在一些关键区别: ‌分类支持‌&#xf…

医疗图像之基于UNet3+(UNet+++)的X射线图像牙齿分割

第一步:准备数据 X射线图像牙齿分割,总共有2000张 第二步:搭建模型 UNet3主要是参考了UNet和UNet两个网络结构。尽管UNet采用了嵌套和密集跳过连接的网络结构(见图1(b)红色三角区域),但是它没有直接从多尺…

探索机器学习中的特征选择技术

在机器学习和数据科学领域,特征选择是一个关键步骤,它不仅有助于提高模型的性能,还能帮助我们更好地理解数据。本文将深入探讨特征选择的重要性、常见方法以及如何在实际项目中应用这些技术。 一、特征选择的重要性 降低维度:减…