JVM学习(十一):对象的实例化内存布局与访问定位

news2024/11/28 14:28:06

目录

一、对象的实例化

1.1 创建对象的方式 

1.2 创建对象的步骤 

二、对象的内存布局

 2.1 对象头

2.1.1 运行时元数据(Mark Word) 

2.1.2 典型指针 

2.2 实例数据(Instance Data)

2.3 对齐填充(Padding)

三、对象的访问定位

1、句柄访问

2、直接指针(Hotspot采用这种方法) 


 

一、对象的实例化

1.1 创建对象的方式 

  •  new
    • 直接new
    • Xxx类的静态方法
    • XxxBuilder 或 XxxFactory的静态方法
  • Class的newInstance():反射的方式,只能用无参构造器,且权限必须为public。jdk8以后不推荐
  • Constructor的newInstance(Xxx):反射的方式,可以用有参和无参构造器,权限无限制
  • 使用clone():不调用任何构造器,当前类需要实现Cloneable接口,实现clone()
  • 使用反序列化:从文件中、网络中获取一个对象的二进制流
  • 第三方库Objenesis

1.2 创建对象的步骤 

        1、判断对象对应的类是否加载、链接、初始化

        首先计算对象占用空间大小,接着在堆中划分一块内存给新对象。如果实例成员变量是引用变量,仅分配引用变量空间即可,即4个字节大小。 

        2、为对象分配内存

                a、如果内存规整(相当于标记-整理算法)

                如果内存是规整的,那么虚拟机将采用的是指针碰撞法( Bump The Pointer )来为对象分配内存。意思是所有用过的内存在一边,空闲的内存在另外一边,中间放着一个指针作为分界点的指示器,分配内存就仅仅是把指针向空闲那边挪动一段与对象大小相等的距离罢了。如果垃圾收集器选择的是Serial、ParNew这种基于压缩算法的,虚拟机采用这种分配方式。一般使用带有
compact(整理)过程的收集器时,使用指针碰撞。

                b、如果内存不规整(相当于标记-清除算法)

                如果内存不是规整的,已使用的内存和未使用的内存相互交错,那么虚拟机将采用的是空闲列表法(Free List ) 来为对象分配内存。意思是虚拟机维护了一个列表,记录上哪些内存块是可用的,再分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的内容。

                c、说明

                选择哪种分配方式由Java堆是否规整决定,而Java堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。

        3、处理并发问题

                a、采用CAS配上失败重试保证更新的原子性

                b、每个线程预先分配一块TLAB

                        通过-XX:+/-UseTLAB参数来设定

        4、初始化分配到的空间

                所有属性设置默认值,保证对象实例字段在不赋值时可以直接使用。

        5、设置对象的对象头

        将对象的所属类(即类的元数据信息)、对象的HashCode和对象的GC信息、锁信息等数据存储在对象的对象头中。这个过程的具体设置方式取决于JVM实现。

        6、执行init方法进行初始化

        在Java程序的视角看来,初始化才正式开始。初始化成员变量,执行实例化代码块,调用类的构造方法,并把堆内对象的首地址赋值给引用变量。因此一般来说(由字节码中是否跟随有invokespecial指令所决定),new指令之后会接着就是执行方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全创建出来。 

        例如我们看这个简单的代码:

public class ObjectTest {
    public static void main(String[] args) {
        Object obj = new Object();
    }
}

        就使用了invokespecial指令:

        细说给对象赋值的操作,可分为:

  1. 属性默认初始化
  2. 显式初始化
  3. 代码块中初始化
  4. 构造器中初始化 
public class Customer{
    // 显式初始化
    int id = 1001;
    String name;
    Account acct;

    //代码块中初始化
    {
        name = "匿名客户";
    }

    // 构造器中初始化
    public Customer(){
        acct = new Account();
    }

}
class Account{

}

         对应的字节码:

  

二、对象的内存布局

 

        对虚拟机栈、堆和方法区不熟的同学,可以看我的文章:

        JVM学习(八):虚拟机栈(字节码程度深入剖析)_玉面大蛟龙的博客-CSDN博客 

        JVM学习(九):堆(万字剖析)_玉面大蛟龙的博客-CSDN博客 

        JVM学习(十):方法区_玉面大蛟龙的博客-CSDN博客 

 2.1 对象头

        包含两部分:运行时元数据(Mark Word)和典型指针。

        如果是数组,还需记录数组的长度。

2.1.1 运行时元数据(Mark Word) 

  • 哈希值(HashCode)
  • GC分代年龄
  • 锁状态标志
  • 线程持有的锁
  •  偏向线程ID
  • 偏向时间戳

2.1.2 典型指针 

        指向类元数据InstanceKlass,确定该对象所属的类型

2.2 实例数据(Instance Data)

        它是对象真正存储的有效信息,包括程序代码中定义的各种类型的字段(包括从父类继承下来的和本身拥有的字段)

        规则:

        相同宽度的字段总是被分配在一起;父类中定义的变量会出现在子类之前;如果CompactFields参数为true(默认为true):子类的窄变量可能插入到父类变量的空隙。 

2.3 对齐填充(Padding)

        不是必须的,也没有特别含义,仅仅起到占位符的作用。

三、对象的访问定位

        创建对象是为了使用它,那么,JVM是如何通过栈帧中的对象引用访问到其内部的对象实例的呢? 

 

        其实是将对象的堆区地址放入栈上的reference上,通过reference定位访问。

        对象访问方式主要有两种:

1、句柄访问

 

        实现:通过栈上的reference指向堆中的句柄池中的指针,再由指针指向对象实例和方法区中的类元数据。

        好处:当对象实例的地址发生变动时(例如:Eden区中from区和to区对象的交换、标记-整理算法中的整理步骤),无需改变reference,因为reference始终指向句柄。

2、直接指针(Hotspot采用这种方法) 

 

        实现:在栈上的reference里直接保存堆中对象实例的地址,在对象中有个指针指向方法区中的类元数据。

        好处:reference直接指向对象实例,效率更高。 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一个奇葩的网络问题,把技术砖家“搞蒙了“

问题现象 客户反馈有一个server端S, 两个client端C1, C2, S的iptables规则对C1, C2都是放通的,但是C2无法连接上S,客户很着急,催我们尽快解决。 这里解释一下,iptables规则是防火墙规则,是linux系统实现防…

【C++刷题集】-- day1

目录 选择题 单选 编程题 组队竞赛⭐ 【题目解析】 【解题思路】(排序 贪心) 删除公共字符⭐ 【题目解析】 【解题思路】(哈希映射) 选择题 单选 1、 以下for循环的执行次数是 ( ) for(int x 0, y 0; (y 123) && (x < 4); x); 是无限循环 循环次数不…

Leetcode刷题之有效的括号

我们的内心和心智&#xff0c;是决定我们未来命运的最强劲的力量。 -- 奥普拉温弗瑞目录 &#x1f341;一.有效的括号 &#x1f34d;1.使用栈实现 &#x1f352;2.完整代码&#xff1a; 题目描述&#xff1a; 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0…

Sonar Qube代码质量检测工具安装及基本使用

Sonar介绍 Sonar Qube是一个开源的代码分析平台&#xff0c;支持Java、Python、PHP、JavaScript、CSS等25种以上的语言&#xff0c;可以检测出重复代码、代码漏洞、代码规范和安全性漏洞的问题。 Sonar Qube可以与多种软件整合进行代码扫描&#xff0c;比如Maven&#xff0c;…

算法套路十七——买卖股票问题:状态机 DP

算法套路十七——买卖股票问题&#xff1a;状态机 DP 状态机DP是一种将动态规划方法应用于有限状态机&#xff08;Finite State Machine&#xff09;的问题求解方法。 状态机DP&#xff08;State Machine DP&#xff09;是一种动态规划的思想&#xff0c;它通常用于解决一些具…

行动元宣布推出面向精密制造领域的智能运动控制解决方案

近日&#xff0c;AI 工业工程化平台行动元宣布推出面向精密制造领域的智能运动控制解决方案。该方案融合大数据模型、数字孪生以及人工智能技术&#xff0c;通过数字化建模、适配、调试等过程&#xff0c;极大提升终端设备集成方案的设计、选型与测试效率&#xff0c;并通过算法…

你不学,我不学,谁来网安,谁来保卫国家!

一、为什么选择网络安全&#xff1f; 这几年随着我国**《国家网络空间安全战略》《网络安全法》《网络安全等级保护2.0》**等一系列政策/法规/标准的持续落地&#xff0c;网络安全行业地位、薪资随之水涨船高。 未来3-5年&#xff0c;是安全行业的黄金发展期&#xff0c;提前…

PCL点云库(6) — Filters模块空间裁剪器类

目录 6.1 3D包围盒裁剪器Class BoxClipper3D< PointT > 6.2 平面裁剪器Class pcl::PlaneClipper3D< PointT > 6.3 立方体过滤Class pcl::CropBox< PointT > 6.4 曲面或多边形过滤 Class pcl::CropHull< PointT > 6.5 完整代码 6.1 3D包围盒裁剪器…

C语言基础:static关键字

本文结合工作经验&#xff0c;研究C语言中static关键字的用法。 文章目录 1 static关键字概念2 用法与使用场景2.1 修饰全局变量2.1.1 代码示例2.1.2 使用场景 2.2 修饰函数2.2.1 代码示例2.2.2 使用场景 2.3 修饰局部变量2.3.1 代码示例2.4.2 使用场景 3 总结 1 static关键字…

第13章:存储过程和存储函数

一、存储过程 1.1理解 含义&#xff1a; 存储过程stored procedure&#xff0c;思想是一组经过预先编译的SQL语句的封装。 存储过程预先存储在MySQL服务器上&#xff0c;需要执行的时候&#xff0c;客户端向服务器端发出调用存储过程的命令&#xff0c;服务器段把这组SQL执…

当我和ChatGPT-4聊完后,我觉得一切可能已经来不及了

飞机上有wifi&#xff0c;了然无味&#xff0c;在万米高空&#xff0c;和ChatGPT-4开始了一场坦诚的沟通&#xff0c;它全程都表现出高情商&#xff0c;以及不断尽量安抚我的情绪&#xff0c;而这&#xff0c;恰恰令我脊背发凉。 部分文字截取 ZM&#xff1a;我能不能理解每次对…

k8s学习-CKS真题-ImagePolicyWebhook容器镜像扫描

目录 题目环境搭建imagePolicyWebhook搭建 解题任务二任务三任务一检查 模拟考题参考 题目 Context cluster上设置了容器镜像扫描器&#xff0c;但尚未完全集成到 cluster 的配置中。 完成后&#xff0c;容器镜像扫描器应扫描并拒绝易受攻击的镜像的使用。 Task 注意&#xff…

5.17 ARM 作业

1. 2.用for循环实现1~100之间的和 13BA 3.xmind

可以找工作的C端的低代码产品,终于让我找到了

目录 写在前面 低代码平台 平台怎么选 各平台区别 为什么选它 写在前面 大家都知道低代码这个叫法是从B端叫起来的&#xff0c;也就是说不管是业务人员还是开发人员&#xff0c;都是企业内部使用。那么有没有C端的&#xff0c;且免费使用的低代码产品呢&#xff1f; 低代码…

一次性能优化思考过程

前言 最近业务上空闲了下来&#xff0c;也是把之前在开发时自身感受比较大的白屏时间放在了主线上去排查优化&#xff0c;这里记录一下笔者对于移动端vConsole脚本的引入问题全过程。 网络脚本与问题定位 对于白屏时间&#xff0c;与网络传输有很大关系&#xff0c;如图&…

该怎样学习网络安全知识?

首先&#xff0c;必须&#xff08;时刻&#xff09;意识到你是在学习一门可以说是最难的课程&#xff0c;是网络专业领域的顶尖课程&#xff0c;不是什么人、随随便便就能学好的。不然&#xff0c;大家都是黑客&#xff0c;也就没有黑客和网络安全的概念了。 很多朋友抱着学一…

#systemverilog# 之 event region 和 timeslot 仿真调度(五)实战

目录 一 问题代码 二 解决方法 2.1 调换代码顺序 2.2 #0 Delay 2.3 uvm class 执行移到re-avtive 2.4 搭建完备的UVM 验证平台 三 预期波形 经过之前文章的学习&#xff0c;想必大家对systemverilog 仿真调度的理解&#xff0c;应该八九不离十了。今天&#xff0c;我们…

基于STM32的NRF24L01 2.4G通讯模块的驱动实验(HAL库)

前言&#xff1a;本文为手把手教学NRF24L01 2.4G通讯模块的驱动实验&#xff0c;本教程的 MCU 采用STM32F103ZET6与STM32F103C8T6&#xff0c;彼此进行互相通讯。通过 CubeMX 软件配置 SPI 协议驱动NRF24L01 2.4G通讯模块&#xff08;HAL库&#xff09;。NRF24L01 2.4G是嵌入式…

渗透测试--5.2.hash密码的破解

目录 1.hashcat简介 2.hashcat参数 常见参数 哈希类型&#xff08;-m&#xff09; 破解模式&#xff08;-a&#xff09; 3.实例 步骤一&#xff1a;使用hash-identifier工具判断哈希值类型 步骤二&#xff1a;使用字典攻击进行破解 1.hashcat简介 hashcat号称世界上最…

js实现点击改变文字大小

目录 一、前言二、代码实现 一、前言 在编写代码之前我们先来看看通过js获取元素有几种方式&#xff1a; 1.第一种 document.querySelector() 返回文档中匹配指定的选择器组的第一个元素document.querySelectorAll(); 返回文档中匹配指定的选择器组的所有元素 <!DOCTYPE ht…