对象的实例化过程

文章目录

    • 1、类加载
    • 2、内存分配
    • 3、初始值为零
    • 4、设置对象头
    • 5、入栈、执行 init 指令
    • 6、Java 对象的内存分布(即实例化后的对象在堆中的分布)
      • 对象头
      • 实例数据
      • 对齐填充
    • 7、对象的访问定位

在这里插入图片描述

1、类加载

当虚拟机遇到一个 new 指令的时候,会先去检测这个指令的参数是否能定位到这个类的符号引用,并检查这个类是否被加载、链接(验证、准备、解析)、初始化过(在 JVM 的方法区中检查)。如果没有,则执行类加载(类加载机制)

2、内存分配

在类加载通过之后,虚拟机将为新生对象分配内存,对象所需内存的大小在类加载完成后便可完全确定,相当于从 Java 堆中抽取一块内存出来;而根据内存的是否绝对规整,分为指针碰撞和空闲列表两种分配方式:

指针碰撞:假设 Java 堆中的内存是绝对规整的,分为空闲和非空闲两种,中间用一个指针当做划分界限的指示器;当一个新对象需要分配对象时,相当于把指针向空闲区域移动一段与对象大小相等的距离。

空闲列表:假设 Java 堆的内存不是绝对规整的,空闲和非空闲是相互交错的,那就需要一个 OopMap 列表,用来记录哪些内存块是可以用的,在对象分配内存时,划分一块大小相等的区域给对象,并更新这个列表

从上面的解释看,用哪种分配方式,是通过 Java 堆的内存块是否绝对规整决定的。

堆内存是否规整,主要是看 GC 回收了内存之后是否包含压缩或者整理功能.如果有,那么内存就比较规整.否则如果没有,创建对象就需要采用空闲列表的方式.

比如:serial,ParNew 等带有整理的收集器,可以使用指针碰撞.

CMS 使用简单清除的算法,可以使用空闲列表.

但对象的创建是频繁的,在并发的情况,多线程不一定是安全的,即存在 A 对象在分配内存,指针还未来得及修改,B 对象也同时使用了原来的指针来分配对象。所以又衍生了两种解决办法,CAS+失败重试 和 TLAB 两种方式

CAS+失败重试:虚拟机采用 CAS 配上失败重试的方式保证更新操作的原子性 (关于 CAS 锁,是乐观锁的一种实现,解释起来也比较麻烦。

TLAB:本地线程分配缓冲,把内存分配的动作按照线程分配划分在不同的空间中进行,即每个线程在 Java 堆中预先分配一小块内存,哪个线程需要需要分配,先在 TLAB 中分配,用完了并重新分配新的 TLAB 时,才需要同步锁定。

3、初始值为零

在内存分配完成之后,虚拟机需要将分配到的内存空间初始化为零值 (除对象头外),这一步操作也保证了对象的实例字段在 java 代码中可以不赋初始值就可以使用,因为程序能访问这些字段的数据类型所对应的零值。

4、设置对象头

初始值设置之后,怎么知道对象是哪个类的实例,如何才能找到类的元数据信息、哈希码、GC 分代年龄等信息呢?这就需要对对象头进行一些必要的设置,才能定位到。

5、入栈、执行 init 指令

从虚拟机来看,对象已经分配产生完成了,且入栈了;但 Java 程序来看,这才刚开始,所以,new 之后,则执行 init 方法,进行初始化。

6、Java 对象的内存分布(即实例化后的对象在堆中的分布)

对象在内存中的存储布局可分为 3 部分:

在这里插入图片描述

对象头

其中对象头又可以细分为两部分:

1、存储对象自身运行时数据:如哈希码、GC 分代年龄、锁状态标志、线程持有的、偏向线程 ID 等信息

2、类型指针:即对象指向它的类元数据的指针,虚拟机通过这个来确定这个对象是哪个类的实例(比如是指向栈中的类声明)

实例数据

是对象真正存储的有效信息,比如程序中定义的各种类型的字段内容,无论父类和子类都会记录下来;在分配时,相同宽度的字段会被分配到一起,这也是父类定义的变量会出现在子类之前的原因。

对齐填充

没啥实际意义,就是为了保证对象是 8 个字节的整数倍,没对齐时,用来补全而已。

7、对象的访问定位

使用对象时,通过栈上的 reference 数据来操作堆上的具体对象。

建立对象是为了使用对象,Java 程序需要通过栈上的 reference 数据来操作堆上的具体对象;但这些访问方式取决于虚拟机实现而定,目前主流有句柄和直接指针两种:

句柄:从 Java 堆中划分出一块内存用来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄包含了对象实例数据与类型数据各自的具体地址信息,如下图(图片来自 Java 虚拟机第三版)

在这里插入图片描述

直接指针:在直接指针中,reference 储存的就是对象地址,所以,需要考虑的是如何防止访问类型数据的相关信息(图片来自 Java 虚拟机第三版)

在这里插入图片描述

优点介绍:
句柄:使用句柄好处是,reference 中存放的是文档的句柄地址,对象被移动时,只改变句柄的实例数据指针,而 reference 本身不需要修改

直接指针:使用直接指针的最大好处就是速度更快,节省了指针定位的开销;

HotSpot 使用第二种方式进行对象访问的.

查看全文

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

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

相关文章:

在这里插入图片描述

对象的实例化过程

文章目录1、类加载2、内存分配3、初始值为零4、设置对象头5、入栈、执行 init 指令6、Java 对象的内存分布(即实例化后的对象在堆中的分布)对象头实例数据对齐填充7、对象的访问定位1、类加载
当虚拟机遇到一个 new 指令的时候,会先去检测这……

TryHackMe-Ghizer(boot2root)

Ghizer
Lucrecia在服务器上安装了多个Web应用程序。 端口扫描
循例 nmap FTP枚举
anonymous进入ftp,发现登录失败 Web枚举
80端口 443端口 目录扫描
先看80,上gobuster, 扫到不少目录 在/docs/release_notes.txt中,暴露了LimeSurvey版本……

为什么说标签限制了我们?放下标签,品生活中的美好

为什么说标签限制了我们?放下标签,品生活中的美好00 导读01 一直在“打标签”的我02 不应该被“标签”所定义03 如何放下标签?04 小结00 导读 大家有多久没仔细观察身边的人和事情了?除了工作需要外,我们有多久没有让自……

【算法】神奇宝贝打BOSS简化模型初步研究:概率dp和期望dp

文章目录引言基础问题基础问题:dp做法基础问题:brute force基础问题:代码扩展1:考虑我方血量扩展1:2维dp扩展1:brute force扩展1:代码扩展2:双方都能攻击或回血引言
今天心血来潮&a……

【ServletConfigServletContext 学习】

基本排序实现 笔记记录一、ServletConfig1. ServletConfig配置方式2. ServletConfig常用方法二、ServletContext1. ServletContext的配置方式2. ServletContext常用方法2. ServletContext常用方法(数据共享)一、ServletConfig 1. ServletConfig配置方式 2. ServletConfig常用方……

Helm安装weave scope

Helm安装weave scope Weave Scope添加chart仓库修改values.yaml安装weave scope验证安装访问测试Weave Scope
Weave Scope 是 Docker 和 Kubernetes 的可视化和监控工具。 它为您的应用程序以及整个基础架构提供了自上而下的视图,并允许您在部署到云提供商时实时诊断分布式容……

Helm 安装 prometheus-operator

Helm 安装 prometheus-operator 环境要求安装国内chart仓库创建命名空间 namespace选择 prometheus-operator 版本安装 prometheus-operator拉取chart持久化存储安装prometheus-operator安装 windows_exporter升级操作删除和卸载注意事项环境要求 helm工具kubernetes 集群版本……

使用ServiceMonitor管理配置监控

使用ServiceMonitor管理配置监控 架构配置部署应用,暴露metrics创建serviceMonitor规则关联Promethues与ServiceMonitor验证是否配置成功为了能够自动化的管理Prometheus的配置,Prometheus Operator使用了自定义资源类型ServiceMonitor来描述监控对象的信息。
架构 配置
部……

添加额外抓取配置

添加额外抓取配置 创建additional configurationAdditionalScrapeConfigs允许指定额外的Prometheus scrape configs的Secret密钥。 指定的scrape configs会附加到Prometheus Operator生成的配置中。
指定的作业配置必须具有Prometheus官方文档中指定的形式。 由于附加了scrape……

自定义 PrometheusRule

自定义 PrometheusRule PrometheusRule 介绍查询默认加入的规则Prometheus 是如何识别自定义 rules 的?PrometheusRule 介绍
PrometheusRule是安装prometheus-operator时默认安装的自定义资源对象(CRD),用来管理Prometheus上的告警规则,后面增删改查规则都可以通过这个资……

深度学习快速参考:11~13

原文:Deep Learning Quick Reference 协议:CC BY-NC-SA 4.0 译者:飞龙 本文来自【ApacheCN 深度学习 译文集】,采用译后编辑(MTPE)流程来尽可能提升效率。 不要担心自己的形象,只关心如何实现目……

基于copula的风光联合场景生成与缩减

目录
1 主要内容
风光出力场景生成方法
2 部分程序
3 程序结果
4 程序链接
点击直达! 1 主要内容
该程序方法复现《融合风光出力场景生成的多能互补微网系统优化配置》风光出力场景生成部分,目前大多数研究的是不计风光出力之间的相关性影响&amp……

TS 使用自动提示生成对象中的键

TS 使用自动提示生成对象中的键
使用 plain object 而不是 class 的原因主要是在于 redux 中保存的对象需要为可序列化的对象。当然,具体操实现的时候肯定是可以无视这个需求的,不过 Redux 团队强烈建议使用可序列化对象,具体的官方文档说明……

Spring Boot概述(一)

1. SpringBoot 概述
1.1 SpringBoot 概念
SpringBoot提供了一种快速使用Spring的方式,基于约定优于配置的思想,可以让开发人员不必在配置与逻辑业务之间进行思维的切换,全身心的投入到逻辑业务的代码编写中,从而大大提高了开发的……

计算机笔试/面试常见逻辑题/智力题汇总

说明:按种类汇总,难度不分先后,做了分级罗列,方便后续扩充,大家有比较有意思的题目可以在讨论区讨论。 下面有的题题解相对复杂的直接参考了网上的一些解答,而有的题解我认为并不好的也做了补充&#xff0c……

OpenAI文档翻译——搭建第一个自己的ChatGPT应用

这篇主要是讲了重头到位创建一个基于OpenAI API的应用程序的过程,同时给出了Node.js、Python版本的实例代码。应用程序的构建总体来说是很简单的就是一个接口调用,前提是我们需要提供密匙。
如果想要获取更好的结果返回一个是可以给模型提供一些列子从而……

python以及PyCharm工具的环境安装与配置

这里以Windows为例
Python的安装
当然是到Python官网下载咯,https://www.python.org/downloads/点我直达,如图: 可以下载最新版本,可以下拉找到之前特定的版本安装,如图: 这里先择的是最新版的进行安装……

JavaScript【六】JavaScript中的字符串(String)

文章目录🌟前言🌟字符串(String)🌟单引号和双引号的区别🌟属性🌟 length :字符串的长度🌟 方法🌟 str.charAt(index);🌟 str.charCodeAt(index);🌟 String.fromCharCode(……

获取文件MD5小案例(未拆分文件)

文章目录前端获取MD5后端获取MD5前端获取MD5
1、引入js
<script src"js/spark-md5.min.js" type"text/javascript"></script>注:spark-md5库GitHub链接 2、这里是一个按钮和被隐藏调的<input/>标签 <body><button……

Java 进阶(15)线程安全集合

CopyOnWriteArrayList
线程安全的ArrayList,加强版读写分离。
写有锁,读⽆锁,读写之间不阻塞,优于读写锁。
写⼊时,先copy⼀个容器副本、再添加新元素,最后替换引⽤。
使⽤⽅式与ArrayList⽆异。
示例……

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注