JVM之对象的内存模型、创建过程、对象引用、生命周期

news/2024/5/19 5:14:53/文章来源:https://blog.csdn.net/qq_38628046/article/details/127142482

JVM之对象的内存模型、创建过程、对象引用、生命周期

  • Java对象内存模型
    • 对象头
    • 实例数据
    • 对齐填充部分
  • 对象的创建
    • 类加载检查
    • 分配内存
    • 初始化零值
    • 设置对象头
    • 执行init方法
  • 引用计数法
  • 对象的引用
    • 强引用
    • 软引用
    • 弱引用
    • 虚引用
  • 对象的生命周期
    • 创建阶段(Created)
    • 应用阶段(In Use)
    • 不可见阶段(Invisible)
    • 不可达阶段(Unreachable)
    • 收集阶段(Collected)
    • 终结阶段(Finalized)
    • 对象空间重新分配阶段(De-allocated)
  • 回收对象

Java对象内存模型

在Hotspot虚拟机中,一个Java对象在内存中的布局可以分为3块区域:对象头、实例数据和对齐填充。
在这里插入图片描述

对象头

Hotspot虚拟机的对象头包括三部分信息:

Mark Word:用于存储对象自身的运行时数据,如:哈希码、GC 分代年龄、锁状态标志等类型指针:对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例数组长度:只有数组对象才有,在32位或者64位JVM中,长度都是32bit

实例数据

实例数据部分是对象真正存储的有效信息,也是在程序中所定义的各种类型的字段内容。

对齐填充部分

对齐填充部分不是必须存在的,没有什么特别含义,仅起占位作用。

Hotspot虚拟机的自动内存管理系统要求对象起始地址必须是8字节的整数倍。对象大小必须是8字节的整数倍,而对象头部分正好是8字节的倍数,因此,当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。

对象的创建

类加载检查

JVM遇到new 指令,会先检查指令的参数能否在常量池中定位到这个类的符号引用,并检查符号引用代表的类是否已被加载过、解析和初始化过。如果没有,则先执行相应的类加载过程。

分配内存

JVM为新生对象分配内存。

对象所需的内存大小在类加载完成后便可确定,为对象分配空间的任务等同于把一块确定大小的内存从 Java 堆中划分出来。

内存分配方式

指针碰撞 :

适用于内存规整即没有内存碎片的情况。用过的内存全部整合到一边,没有用过的内存放在另一边,中间有一个分界指针,只需要向着没用过的内存方向将该指针移动对象内存大小位置即可分配GC收集器:Serial, ParNew

空闲列表 :

适用于堆内存不规整的情况。虚拟机会维护一个列表,该列表中会记录哪些内存块是可用的,在分配的时候,找一块儿足够大的内存块儿来划分给对象实例,最后更新列表记录。分配GC收集器:CMS

具体内存分配取决于 Java 堆内存是否规整,而Java堆内存是否规整,取决于GC收集器的算法是标记-清除,还是标记-整理,复制算法内存也是规整的。

初始化零值

JVM将分配到的内存空间都初始化为零值,不包括对象头,保证对象实例字段在 Java 代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。

设置对象头

JVM对对象进行必要设置,如对象是哪个类实例、如何找到类元数据信息、对象哈希码、对象GC分代年龄等信息。

执行init方法

此时,从JVM来看,一个新对象已经产生了。从Java程序来看,对象创建才刚开始,init>方法还没有执行,所有字段都为零。

所以,执行new指令之后会接着执行init方法,把对象按照开发者意愿进行初始化,这样一个真正可用的对象才算完全产生出来。

引用计数法

给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器都为0的对象就是不再被使用的,垃圾收集器将回收该对象使用的内存。

优缺:

引用计数收集器可以很快的执行,交织在程序运行中。对程序需要不被长时间打断的实时环境比较有利。无法检测出循环引用。如父对象有一个对子对象的引用,子对象反过来引用父对象。这样,他们的引用计数永远不可能为0.而且每次加减非常浪费内存。

对象的引用

强引用

在Java中最常见的就是强引用:把一个对象赋给一个引用变量,这个引用变量就是一个强引用。

当一个对象被强引用变量引用时,它处于可达状态,它是不可能被垃圾回收机制回收的,即使该对象以后永远都不会被用到JVM 也不会回收。因此强引用是造成Java内存泄漏的主要原因之一。

软引用

软引用需要用SoftReference类来实现,对于只有软引用的对象来说,当系统内存足够时它不会被回收,当系统内存空间不足时它会被回收。软引用通常用在对内存敏感的程序中。

    public static void main(String[] args) {// 使用user实例User user = new User();user.setName("小白");user.setAge(20);System.out.println("user = " + user);// 使用完user,将它设置为soft引用类型,并且释放强引用SoftReference softReference = new SoftReference(user);user = null;if (softReference != null) {user = (User) softReference.get();} else {// GC由于内存资源不足,可能系统已回收user的软引用,因此需要重新装载user = new User();user.setName("大白");user.setAge(30);softReference = new SoftReference(user);}System.out.println("user = " + user);}

弱引用

弱引用需要用WeakReference类来实现,它比软引用的生存期更短,对于只有弱引用的对象来说,只要垃圾回收机制一运行,不管JVM的内存空间是否足够,总会回收该对象占用的内存。

    public static void main(String[] args) throws InterruptedException {// bytes对象byte[] bytes = "Java".getBytes();// 将bytes对象用弱引用持有WeakReference<byte[]> bytesRef = new WeakReference<>(bytes);System.out.println("第一次GC前" + bytes);// 进行一次GC后查看对象的回收情况System.gc();// 等待GCThread.sleep(1000);System.out.println("第一次GC后" + bytes);// 将bytes对象的强引用去除bytes = null;// 等待GCSystem.gc();Thread.sleep(1000);System.out.println("第二次GC后" + bytes);}
第一次GC前[B@1e81f4dc
第一次GC后[B@1e81f4dc
第二次GC后null

虚引用

虚引用需要PhantomReference类来实现,它不能单独使用,必须和引用队列联合使用。虚引用的主要作用是跟踪对象被垃圾回收的状态。

对象的生命周期

在Java中,对象的生命周期包括:创建阶段、应用阶段、不可见阶段、不可达阶段、收集阶段、终结阶段、对象空间重分配阶段等几个阶段。
在这里插入图片描述

创建阶段(Created)

为对象分配存储空间开始构造对象从超类到子类对static成员进行初始化超类成员变量按顺序初始化,递归调用超类的构造方法子类成员变量按顺序初始化,子类构造方法调用一旦对象被创建,并被分派给某些变量赋值,这个对象的状态就切换到了应用阶段

应用阶段(In Use)

对象至少被一个强引用持有着

不可见阶段(Invisible)

当一个对象处于不可见阶段时,说明程序本身不再持有该对象的任何强引用,虽然这些引用仍然是存在着的。

不可达阶段(Unreachable)

对象处于不可达阶段是指该对象不再被任何强引用所持有。

可见阶段是指程序不再持有该对象的任何强引用,这种情况下,该对象仍可能被JVM等系统下的某些已装载的静态变量或线程或JNI等强引用持有着,这些特殊的强引用被称为”GC root ”。存在着这些GC root会导致对象的内存泄露情况,无法被回收。

收集阶段(Collected)

当垃圾回收器发现该对象已经处于不可达阶段并且垃圾回收器已经对该对象的内存空间重新分配做好准备时,则对象进入了收集阶段。

如果对象重写finalize() 方法,则会去执行该方法的终端操作。建议不要重载finazlie()方法

1.会影响JVM的对象分配与回收速度

在分配该对象时,JVM需要在垃圾回收器上注册该对象,以便在回收时能够执行该重载方法。在该方法的执行时需要消耗CPU时间且在执行完该方法后才会重新执行回收操作,即至少需要垃圾回收器对该对象执行两次GC。

2.可能造成该对象的再次复活

在finalize()方法中,如果有其它的强引用再次持有该对象,则会导致对象的状态由收集阶段又重新变为应用阶段。已经破坏了Java对象的生命周期进程,且复活对象不利用后续的代码管理。

终结阶段(Finalized)

当对象执行完finalize()方法后仍然处于不可达状态时,则该对象进入终结阶段。在该阶段是等待垃圾回收器对该对象空间进行回收。

对象空间重新分配阶段(De-allocated)

垃圾回收器对该对象的所占用的内存空间进行回收或者再分配了,则该对象彻底消失了,称之为对象空间重新分配阶段。

回收对象

GC是由JVM自动完成的,根据JVM系统环境而定,因此,垃圾回收时机是不确定的,即回收对象时机是不确定的。

可以手动进行垃圾回收,如调用System.gc()方法通知JVM进行一次垃圾回收,但具体什么时候运行无法控制。不建议手动调用该方法,因为GC消耗的资源比较大。

通常在以下情况会进行对象垃圾回收

Eden区或者S区不够用老年代空间不够用方法区空间不够用System.gc()

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

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

相关文章

代理ARP (路由式代理ARP+vlan内代理ARP+vlan间代理ARP) [理论+实验验证]

衷心感谢三位大佬的博客 ! ! ! ! 这篇博客主要是为了记录笔记方便查看而整理&#xff0c; 主要内容整理来源&#xff1a; (58条消息) 代理ARP实验_在下小黄的博客-CSDN博客_arp代理实验 (58条消息) 代理ARP_士别三日wyx的博客-CSDN博客_arp代理 (59条消息) 华为ARP代理的三种方…

字节在职三年,如何想要三个月内将软件测试学好,我建议你这样学

目录 13年本科毕业&#xff0c;目前已经工作将近7年时间&#xff0c;第一段工作是在字节工作3年时间&#xff0c;目前是再另外一家大厂工作。今天跟大家分享一下我工作的心得&#xff0c;希望对你有所帮助 我对软件测试的理解 软件测试是软件开发的最后一道防线&#xff0c;…

【Vue 快速入门系列】样式绑定与条件渲染

文章目录前言样式绑定条件渲染前言 在vue中好像一切数据都是可以动态的&#xff0c;那么我们应如何让dom元素中的样式动起来呢&#xff1f;我们既然可以改变dom元素的样式&#xff0c;我们能不能将其隐藏起来呢&#xff1f;今天将会介绍到Vue中如何将属性与dom元素的样式进行绑…

Java List 扩容机制探究(ArrayList 、Vector、LinkedList)

文章目录List扩容ArrayList 扩容机制结论&#xff1a;无参构造创建的ArrayList的初始空间为0&#xff0c;在添加第一个元素的时候空间会默认为10&#xff0c;之后扩容会为当前容量的1.5倍。0->10->15->22->33->49源码分析1.ArrayList list new ArrayList();2. …

Android多媒体架构

Android多媒体架构 要实现我们的媒体播放器 主要使用的就是android media MediaPlayer 这样的一个类 来为我们的播放器的实现提供一个主要功能 而这个类的实现又依赖于 JNI层的 1)一些接口 2)Libmedia.so 库 (这个库才是 mediaplayer类的真正实现) 再往下就是我们的se…

产品能力|书山有路-趣味算法(第二版)读书笔记part1

系列文章目录 趣味算法&#xff08;第二版&#xff09;读书笔记&#xff1a; day1: 序章|学习的方法和目标. day2:算法之美|打开算法之门与算法复杂性 day3.算法之美|函数特性与图形 day4.数学之美|斐波那契数列 后续补充完善 提示&#xff1a;写完文章后&#xff0c;目录可以…

Kubernetes_16_静态Pod网关apiserver的audit审计日志

系列文章目录 文章目录系列文章目录前言一、理论&#xff1a;kube-apiserver的审计日志1.1 kube-apiserver.yaml 文件的五行修改1.2 audit-policy.yaml文件的修改二、实践&#xff1a;编写策略文件&#xff0c;打印想要的审计日志2.1 步骤1&#xff1a;编写修改policy.yaml文件…

05_排序与分页

1.排序数据 1.1排序规则 如果没有使用排序操作&#xff0c;默认情况下查询返回的数据是按照添加数据的顺序显示的。 使用ORDER BY子句排序 ASC (ascend):升序 DESC (descend):降序 ORDER BY子句在SELECT语句的结尾。 1.2单列排序 1.简单使用排序 #如果没有使用排序操作&am…

每日算法、面试题

目录 2022/10/16 一、算法 翻转字符串里的单词 找出字符串中第一个匹配项的下标 二、面试题 SpringMvc中如何解决POST请求的中文乱码问题 SpringMvc的工作流程 2022/10/16 一、算法 翻转字符串里的单词 给你一个字符串 s &#xff0c;请你反转字符串中 单词 的顺序。 …

【Nginx】三、Nginx实现四层负载均衡Nginx实现限流防盗链流量镜像

Nginx实现四层负载均衡一、Nginx实现四层负载均衡1、四层负载均衡与七层负载均衡区别2、Nginx四层负载均衡配置3、SocketTool工具4、TCP&UDPDebug工具二、Nginx实现限流三、Nginx实现防盗链四、Nginx流量镜像一、Nginx实现四层负载均衡 我们之前介绍的HTTP负载均衡&#x…

Silane-PEG-Alkyne,硅烷-聚乙二醇-炔基用于修饰蛋白类

An English name&#xff1a;Silane-PEG-Alkyne Chinese name&#xff1a;硅烷-聚乙二醇-炔基 Item no&#xff1a;X-GF-0314-10k CAS&#xff1a;N/A Formula&#xff1a;N/A MW&#xff1a;Silane-PEG-Alkyne5000、Silane-PEG-Alkyne3400、Silane-PEG-Alkyne2000、硅烷-…

【附源码】计算机毕业设计SSM美食菜谱网站

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

(附源码)计算机毕业设计SSM基于JAVA线上订餐系统

&#xff08;附源码&#xff09;计算机毕业设计SSM基于JAVA线上订餐系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术…

【Vue Router】

资料 官网&#xff1a;https://v3.router.vuejs.org/zh/guide/ 尚硅谷视频&#xff1a;https://www.bilibili.com/video/BV1Zy4y1K7SH?p118 基本使用 安装&#xff1a; 这里安装vue3.x vue 2.x 版本对应 vue-router 3.xvue 3.x 版本对应 vue-router 4.x其他以此类推 npm…

【数据结构】------ 堆

目录 堆的概念及结构 堆的实现 堆向上调整算法 堆向下调整算法 堆的创建 堆的初始化和销毁 堆的插入 堆的删除 获取堆顶的数据 获取堆的数据个数 堆的判空 TopK问题&#xff08;在N个数找出最大&#xff08;小&#xff09;的前K个&#xff09; 堆排序 堆的概念及…

自学Python第二十七天- 简单部署生产环境,docker 的使用

自学Python第二十七天- 部署极简生产环境Windows 环境部署创建绿色 python 环境Linux 环境部署创建 Linux 环境使用Hyper-V使用 VMware 部署使用 docker 部署docker 原理安装 docker使用 linux 系统使用包管理工具使用 docker 仓库使用源代码安装使用 windows 系统开启 docker …

寻路算法-从bfs到Astart

一、简单BFS算法 bfs即广度优先搜索&#xff0c;最基础的寻路算法 即向出发点向四周无目的扩散&#xff0c;知道到达终点或者无法扩散为止 # coding: utf-8import random import bisectclass Solution(object):def __init__(self, n, m, bad):self.map [[0, 0, 0, 0, 0, 0, …

1.4. PUBLIC KEYS AS IDENTITIES公钥及身份 1.5. TWO SIMPLE CRYPTOCURRENCIES两种简单加密货币

《BITCOIN AND CRYPTOCURRENCY TECHNOLOGIES》Chapter 1系列 1.4. PUBLIC KEYS AS IDENTITIES 公钥作为身份 从一个签名方案中提取一个公钥将之视为一个身份。 公钥 public key 可以代表私钥 private key 的公众身份&#xff0c;而 private key 则是此人身份真实的内涵。 随时…

Linux服务搭建 -- NTP服务

什么是NTP&#xff1f; NTP全名“Network TimeProtocol”&#xff0c;即网络时间协议&#xff0c;是由RFC 1305定义的时间同步协议&#xff0c;用来在分布式时间服务器和客户端之间进行时间同步。 NTP基于UDP报文进行传输&#xff0c;使用的UDP端口号为123。使用NTP的目的是对网…

QFramework v1.0 使用指南 工具篇:03. CodeGenKit 脚本生成

在这一篇&#xff0c;我们学习几乎每个项目都要用到并且从中受益的功能&#xff1a;自动生成脚本并绑定&#xff0c;简称脚本生成。 基本使用 我们先在场景中&#xff0c;随便创建一些有父子结构的 GameObject&#xff0c;如下所示&#xff1a; 接着给 Player 挂上 ViewContr…