深入理解java虚拟机(五)

简介: 深入理解java虚拟机(五)

一、Java虚拟机栈不存储运行时的数据,

比如声明一个String a="abc";,这个变量是在方法区还是堆呢?

如果存放在堆的话,这时就在堆里面分配一块内存,如果在声明一个String b="abc"

如果存放堆的话,也会在堆里面分配一块内存。

a==b;//true

如果a,b变量都在堆里面分配内存的话,就为false,所以常量的分配内存不是在堆里面分配的

而是在方法区里面分配的。方法区里面采用StringTable(HashSet)维护的。

如果存放了abc的话,b就存放布进去了。这时a与b就相等了。

String c=new String("abc");

c.intern()==a;//true

intern():方法的作用将内存地址移动到方法区的常量池里面

二、你的对象是怎么什么来的?

简介:java程序员不可不知的对象创建地测才能够步骤细节

1、对象创建的流程步骤包括哪些:比如 A a=new A();

    ①、虚拟机遇到一条new指令时,首先检查这个对应的类能否在常量池中定位到一个类的符号引用。如果能定位到的话,这个类就是在常量池里面存在的。

init方法:static修饰的方法/代码块。

     ②、判断这个类是否已被加载 ,解析和初始化(加载的步骤))

     ③、为这个新生对象在java堆中分配内存空间,其中java堆分配内存空间的方式主要有以下两种:几乎所有的对象和数组的创建都是在Java堆里面创建的。

A、指针碰撞

在上面的图代表堆内存。FREE代表的是空闲内存,USE代表已经使用内存。

当为对象分配一块内存的时候,会将使用的内存扩大,将空闲的内存缩小

中间的部分就是对象所分配的内存。将这种分配内存的方式称之为指针碰撞。

    总结:Ⅰ、分配内存空间包括开辟一块内存和移动指针两个步骤

               Ⅱ、两个步骤可能会非原子步骤可能出现并发问题,java虚拟机采用CAS配上失败重试的方式保证更新操作的原子性。java虚拟机采用的是乐观锁的方式会进行cas的判断比如这边有两个步骤,在维护空闲列表的时候,就可以进行cas的判断预期值和插入的值是否进行匹配,如果匹配的话,就可以操作如果不匹配,就进行重试,这就是cas的乐观锁的原理。

B、空闲列表

java堆内存对象的内存分布,有可能是不均匀的。比如说内存分布非常的乱的时候,就无法通过指针碰撞的时候给对象分配内存。称这种方式为空闲列表:存储堆内存的分配的空闲的地址

在Free区可能内存是一块一块的,空闲列表所维护的就是不规则,不连续的内存。这几块内存就可以通过空闲列表进行维护,维护的就是空闲内存的地址。如果当某个地址被用的时候,就可以从空闲列表里面剔除。

          总结:  Ⅰ、分配内存空间包括开辟一块内存和修改空闲列表的两个步骤

                     Ⅱ、两个步骤可能会非原子步骤可能出现并发问题,java虚拟机采用CAS配上失败重试的方式来保证更新操作的原子性。java虚拟机采用的是乐观锁的方式,会进行cas的判断,比如这边有两个步骤,在维护空闲列表的时候,就可以进行cas的判断预期值和插入的值是否进行匹配,如果匹配的话,就可以操作,如果不匹配,就进行重试,这就是cas的乐观锁的原理。

2、将分配的内存空间都初始化为零值:java虚拟机自己帮做的

3、设置对象相关的数据

       GC分代年龄

       对象的哈希码hashcode

       元数据信息

4、执行对象的<init>方法,比如static方法/代码块是在创建对象之前创建的。


三、java对象内存布局:

A a1=new A();在创建对象的时候,会在堆中给这个对象A开辟一块内存。

那么这个A对象里面包含那几个部分呢?

数据类型,对象的属性,属性的值称之为实例数据

而且所有的类都继承Object类,hashCode的值也是属于对象里面的一部分。

hashcode肯定是存储在内存里面。

锁状态标识:代表当前对象是否持有锁  

GC分代年龄:java虚拟机要对垃圾进行回收,将所回收的垃圾分成了新生代和老年代

java虚拟机在进行回收的时候就会分不同的年代,采用不同的回收的策略,回收算法进行回收

基本的回收算法有三种:标记清除,标记整理,复制算法。那么在不同的GC年代里面采用的回收算法就不一样。GC分代年龄就是在垃圾回收的时候所设置的概念。

锁状态:就是多线程在操作这个对象的时候,为了保证线程安全,所设置的概念。

比如说当前的线程占用了这把锁标识了这把锁,就是锁占用的状态。

线程持有的锁:就是这个线程所占有锁的指针。

对象头还有一个名词是 Mark Word

类型指针:为了定位在方法区里面是哪个类,指向方法区

对象头是在64位的系统里面,占的内存就是64位,如果在32位系统里面占用的内存是32位。

64位和32位都是8的倍数,对象在存储的时候会保持一种原则:保持8的倍数。

对其填充:存储的是对象的数据是占位符,因为对象头Header已经保证了8的倍数,实例数据无法保证8的倍数,那么对齐填充,为了实例数据保持8的倍数。

四、你是怎么访问你的对象的

简介:java程序员不可不知的对象访问定位方式

1、当我们在堆上创建一个对象实例后,就要通过虚拟机栈中的reference类型数据操作堆上的对象。现在主流大的访问方式有两种(Hotspot虚拟机中采用的是第二种)

    ①、使用句柄访问对象,即reference中存储的是对象 句柄的地址,而句柄中包含了对象实例数据与类型数据的具体的地址信息,相当于二级指针

对应另外一种访问是对象句柄访问

句柄访问是在堆里面开辟一块内存,用来存储句柄池:就是存储访问句柄的池子

也就是存储访问的指针。它会存储对象类型是数据的指针,和对象实例数据的指针。

    ②、直接指针访问对象,即reference中 存储的就是对象 地址,相当于一级指针。

写个main方法,main方法是对应java虚拟机中的栈

在方法栈的本地变量表里面,做一个对象的访问:User  user=new User();

user.getId();

对User对象的访问主要访问的是,刚才写到在对象里面存储的是User对象的实例数据

除了实例数据还有对象的类型数据,下面的是实例数据

对象类型数据:Class文件有哪些类型,实例,实现的方法,接口,这些数据称之为对象的类型数据。

对象的访问就是访问它的对象的实例数据和对象的类型数据。

直接指针访问:局部变量表是在java栈里面的,里面存储对对象的访问的指针reference

通过reference就可以对应到堆上面的对象的实例数据,那么在堆里面也会存储对象的类型数据的指针,通过这个指针指向方法区的对象类型数据(Class文件肯定是放到方法区里面的)。

堆会存放对象类型数据的指针,和对象的实例数据。

直接访问就是对对象实例数据和对对象类型数据的指针的访问。


对比:

  垃圾回收分析:方式1当垃圾回收移动对象时,reference中存储的地址是稳定的地址,不需要修改,仅仅需要修改对象句柄的地址;方式2垃圾回收需要修改reference中的存储地址

   访问效率分析:方式二优于方式一,因为方式二只进行了一次指针定位,节省了时间开销,而这也是Hotspot采用的实现方式。

相关文章
|
5天前
|
云安全 监控 安全
|
2天前
|
存储 机器学习/深度学习 人工智能
打破硬件壁垒!煎饺App:强悍AI语音工具,为何是豆包AI手机平替?
直接上干货!3000 字以上长文,细节拉满,把核心功能、使用技巧和实测结论全给大家摆明白,读完你就知道这款 “安卓机通用 AI 语音工具"——煎饺App它为何能打破硬件壁垒?它接下来,咱们就深度拆解煎饺 App—— 先给大家扒清楚它的使用逻辑,附上“操作演示”和“🚀快速上手不踩坑 : 4 条核心操作干货(必看)”,跟着走零基础也能快速上手;后续再用真实实测数据,正面硬刚煎饺 App的语音助手口令效果——创建京东「牛奶自动下单神器」口令 ,从修改口令、识别准确率到场景实用性,逐一测试不掺水,最后,再和豆包 AI 手机语音助手的普通版——豆包App对比测试下,简单地谈谈煎饺App的能力边界在哪?
|
10天前
|
机器学习/深度学习 人工智能 自然语言处理
Z-Image:冲击体验上限的下一代图像生成模型
通义实验室推出全新文生图模型Z-Image,以6B参数实现“快、稳、轻、准”突破。Turbo版本仅需8步亚秒级生成,支持16GB显存设备,中英双语理解与文字渲染尤为出色,真实感和美学表现媲美国际顶尖模型,被誉为“最值得关注的开源生图模型之一”。
1180 7
|
1天前
|
人工智能
自动化读取内容,不会写爆款的普通人也能产出好内容,附coze工作流
陌晨分享AI内容二创工作流,通过采集爆款文案、清洗文本、智能改写,实现高效批量生产。五步完成从选题到输出,助力内容创作者提升效率,适合多场景应用。
205 104
|
16天前
|
人工智能 Java API
Java 正式进入 Agentic AI 时代:Spring AI Alibaba 1.1 发布背后的技术演进
Spring AI Alibaba 1.1 正式发布,提供极简方式构建企业级AI智能体。基于ReactAgent核心,支持多智能体协作、上下文工程与生产级管控,助力开发者快速打造可靠、可扩展的智能应用。
1183 41
|
4天前
|
人工智能 安全 前端开发
AgentScope Java v1.0 发布,让 Java 开发者轻松构建企业级 Agentic 应用
AgentScope 重磅发布 Java 版本,拥抱企业开发主流技术栈。
339 13
|
16天前
|
人工智能 前端开发 算法
大厂CIO独家分享:AI如何重塑开发者未来十年
在 AI 时代,若你还在紧盯代码量、执着于全栈工程师的招聘,或者仅凭技术贡献率来评判价值,执着于业务提效的比例而忽略产研价值,你很可能已经被所谓的“常识”困住了脚步。
960 78
大厂CIO独家分享:AI如何重塑开发者未来十年
|
11天前
|
存储 自然语言处理 测试技术
一行代码,让 Elasticsearch 集群瞬间雪崩——5000W 数据压测下的性能避坑全攻略
本文深入剖析 Elasticsearch 中模糊查询的三大陷阱及性能优化方案。通过5000 万级数据量下做了高压测试,用真实数据复刻事故现场,助力开发者规避“查询雪崩”,为您的业务保驾护航。
572 32