JVM-0426

news2024/11/14 16:22:08

对象内存布局

对象的实例化

  1. 创建对象的方式:

    1. new
      1. 最常见的方式
      2. 变形1:XX的静态方法 Class : 调用froName( )方法
      3. 变形2:xxxBuilder / xxxFactory的静态方法
    2. Class的newInstance( ):反射的方式,只能调用空参的构造器,权限必须是public
    3. Constructor的newInstance( ):反射的方式,可以调用空参、带参的构造器,权限没有要求。
    4. 使用clone( ):不调用任何构造器,当前类需要实现Cloneable接口,实现clone(),默认浅拷贝
    5. 使用反序列化:从文件中、数据库中、网络中获取一个对象的二进制流,反序列化为内存中的对象
    6. 第三方库Objenesis,利用了asm字节码技术,动态生成Constructor对象区
  2. 创建对象的步骤:(字节码角度看待对象创建的过程)

    1. Customer cust2 = new Customer("Tom");
      
      对应的字节码:
      
       0 new #2 <com/atguigu/java/Customer>
       3 dup
       4 ldc #3 <Tom>
       6 invokespecial #4 <com/atguigu/java/Customer.<init> : (Ljava/lang/String;)V>
       9 astore_1
      
    2. 步骤解读:

      1. new:创建新对象,操作数栈里面的引用指向堆空间
      2. dup:复制一份,目的就是为了调用init方法,调完init方法,操作数栈里面的复制品就被弹出去了
      3. 将常量“Tom”加载进操作数栈
      4. 调用init方法,给对象成员初始化
      5. 存储到局部变量表中
  3. 创建对象的步骤:(执行步骤角度分析)

    1. 判断对象对应的类是否加载、链接、初始化
      • 虚拟机遇到一条new指令,首先去检查这个指令的参数能否在Metaspace的常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化。(即判断类元信息是否存在)。
        • 如果没有,那么在双亲委派模式下,使用当前类加载器以ClassLoader+包名+类名为Key进行查找对应的.class 文件。
        • 如果没有找到文件,则抛出ClassNotFoundException 异常。
        • 如果找到,则进行类加载,并生成对应的Class类对象。
    2. 为对象分配内存
      0. 首先计算对象占用空间大小,接着在堆中划分一块内存给新对象。如果实例成员变量是引用变量,仅分配引用变量空间即可,即4个字节大小。说明:选择哪种分配方式由Java堆是否规整决定,而Java堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。
      1. 指针碰撞
        • 如果内存规整,使用指针碰撞
          如果内存是规整的,那么虚拟机将采用的是指针碰撞法(Bump The Pointer)来为对象分配内存。意思是所有用过的内存在一边,空闲的内存在另外一边,中间放着一个指针作为分界点的指示器,分配内存就仅仅是把指针向空闲那边挪动一段与对象大小相等的距离罢了。如果垃圾收集器选择的是Serial、ParNew这种基于压缩算法的,虚拟机采用这种分配方式。一般使用带有compact(整理)过程的收集器时,使用指针碰撞。
      2. 空闲列表
        • 如果内存不规整,虚拟机需要维护一个列表,使用空闲列表分配
          如果内存不是规整的,己使用的内存和未使用的内存相互交错,那么虚拟机将采用的是空闲列表法来为对象分配内存。意思是虚拟机维护了一个列表,记录上哪些内存块是可用的,再分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的内容。这种分配方式称为“空闲列表(Free List)”
    3. 处理并发安全问题
      1. 在分配内存空间时,另外一个问题是及时保证new对象时候的线程安全性:创建对象是非常频繁的操作,虚拟机需要解决并发问题。虚拟机采用了两种方式解决并发问题:
        1. CAS ( Compare And Swap )失败重试、区域加锁:保证指针更新操作的原子性。
        2. TLAB(线程在堆中分配私有空间) 把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配级冲区,(TLAB, Thread Local Allocation Buffer)虚拟机是否使用TLAB,可以通过-XX:+/-Use TLAB参数来设定
    4. 初始化分配到的空间
      • 内存分配结束,虚拟机将分配到的内存空间都初始化为零值(不包括对象头)。这一步保证了对象的实例字段在Java代码中可以不用赋初始值就可以直接使用,程序能访问到这些字段的数据类型所对应的零值。
    5. 设置对象的对象头
      • 将对象的所属类(即类的元数据信息)、对象的HashCode和对象的GC信息、锁信息等数据存储在对象的对象头中。这个过程的具体设置方式取决于JVM实现。
    6. 执行init方法进行初始化(显示初始化)
      • 在Java程序的视角看来,初始化才正式开始。初始化成员变量,执行实例化代码块,调用类的构造方法,并把堆内对象的首地址赋值给引用变量。
      • 因此一般来说(由字节码中是否跟随有invokespecial指令所决定),new指令之后会接着就是执行方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全创建出来。
    7. 所以说,new是造对象,而构造器仅仅是init显式初始化。

对象的内存布局

请添加图片描述请添加图片描述

  1. 对象实例的组成:实例数据和对象头
  2. 实例数据:就是我们可以看见的,类的各种属性
    1. 父类的实例数据:也会继承父类的实例熟悉,可以继承的属性,私有的属性也会存放在这里,但是可能没法直接调用。
    2. 摆放问题:这里需要遵循的一些规则
      1. 相同宽度的字段总是被分配在一起
      2. 父类中定义的变量会出现在子类之前(因为父类的加载是优先于子类加载的)
      3. 如果CompactFields参数为true(默认为true):子类的窄变量可能插入到父类变量的空隙
  3. 对象头:分为类型指针和运行时元数据
    1. 类型指针:指向方法区对应Class实例的指针,getClass()方法调用可以访问对应类
    2. 运行时元数据:
      1. 哈希值(hashcode):对象在堆空间中都有一个首地址值,栈空间的引用根据这个地址指向堆中的对象,这就是哈希值起的作用
      2. GC分代年龄:对象首先是在Eden中创建的,在经过多次GC后,如果没有被进行回收,就会在survivor中来回移动,其对应的年龄计数器会发生变化,达到阀值后会进入养老区
      3. 锁状态标志:表示这个对象是否被锁定了,代表这个锁。
      4. 线程持有的锁
      5. 线程偏向ID
      6. 偏向时间戳
    3. 此外,如果对象是一个数组,对象头中还必须有一块用于记录数组的长!因为正常对象元数据就知道对象的确切大小。所以数组必须得知道
  4. 对象填充:就是占位符作用,填补成完整的内存块,可能是以KB为单位或者其他类似。

对象的访问定位

  1. 创建对象的目的是为了使用它。定位,通过栈上reference访问。
    • JVM是如何通过栈帧中的对象引用访问到其内部的对象实例的呢?
    • 请添加图片描述
  2. 《java虚拟机规范》没有说明,所以对象访问方式由虚拟机实现而定。主流有两种方式:
    1. 使用句柄访问
    2. 使用直接指针访问
  3. 直接使用指针访问:
    1. 使用存储在栈帧里面的引用值去访问变量
    2. 请添加图片描述
  4. 句柄访问:(Java没有采取这种方式)
    1. 实现:堆需要划分出一块内存来做句柄池,reference中存储对象的句柄池中包含对象实例与类型数据各自具体的地址信息。
    2. 好处:reference中存储稳定句柄地址,对象被移动(垃圾收集时移动对象只会改变句柄中实例数据指针,reference本身不需要被修改。
    3. 请添加图片描述

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

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

相关文章

自动控制原理笔记-频率响应法-频率特性的概念

目录 频率响应法&#xff1a; 频率特性的概念&#xff1a; 一、频率特性的定义&#xff1a; 二、频率特性的求法: 三、频率特性的物理意义: 四、频率特性的图形表示方法: 频率响应法&#xff1a; 基本思想&#xff1a;通过开环频率特性的图形对系统进行分析。 主要优点&…

【2023华中杯数学建模】B 题 小学数学应用题相似性度量及难度评估详细建模方案及实现代码

更新时间&#xff1a;2023-5-1 14:00 1 题目 B 题 小学数学应用题相似性度量及难度评估 某 MOOC 在线教育平台希望能够进行个性化教学&#xff0c;实现用户自主学习。在用户学习时&#xff0c;系统从题库中随机抽取若干道与例题同步的随堂测试题&#xff0c;记录、分析学生的学…

java的类加载浅析

类加载 类加载器 类加载器是Java虚拟机&#xff08;JVM&#xff09;的一个组成部分&#xff0c;它的主要任务是在运行时动态加载类和资源&#xff0c;以便程序能够使用它们。类加载器从文件系统、网络或其他来源中获取类的字节码&#xff0c;并将其转换为JVM可执行的形式&…

机器学习基础知识之交叉验证

文章目录 交叉验证定义1、随机子抽样验证2、K折交叉验证3、留一法交叉验证4、自助采样验证 交叉验证定义 在使用某一个数据集对模型进行训练时&#xff0c;模型的实际训练情况会受到数据集的直接影响&#xff0c;且其实际训练结果是难以确定的&#xff0c;极有可能出现欠拟合与…

【实验报告】实验四、彩色图像处理

一、实验目的 使用MatLab软件对图像进行彩色处理&#xff0c;熟悉使用MatLab软件进行图像彩 色处理的有关方法&#xff0c;并体会到图像彩色处理技术以及对图像处理的效果。 二、实验原理 &#xff08;一&#xff09;一幅RGB图像就是彩色像素的一个M x N x 3数组&#xff0…

视频搬砖项目【一个技术员是如何轻松利用视频搬运项目做到日入2000+】

无门槛人人可做副业项目&#xff0c;视频搬砖收益&#xff0c;实测一天2000&#xff01; 今天给大家分享一个微信看一看 的项目&#xff0c;操作非常简单&#xff0c;小白也很容易上手&#xff0c;不需要像某音一样去卖货&#xff0c;只要发布作品就能够有收益。 第一个、项目…

vue项目无法运行报错 error:0308010C:digital envelope routines::unsupported

文章目录 问题原因解决方法方法一方法二 问题 运行vue项目&#xff0c;报错 error:0308010C:digital envelope routines::unsupported 原因 网上查了一下&#xff0c;大体原因就是node版本不对&#xff0c;node版本太高 也有说我没有使用 Node JS 的 LTS&#xff08;长期支…

ROS2交叉编译操作

ROS2移植过程 在移植ROS2之前,先确认需要移植的版本以及其对应的依赖,这些信息可以在 ROS 2 Releases and Target Platforms 中有介绍,可依据自身需要使用的平台,参考该链接进行选择,下面以ROS2 Humble为例进行介绍ROS2移植操作。 ROS Humble依赖如下: 而ROS2的构建依赖…

sed进阶之保留空间和排除命令

shell脚本编程系列 保留空间 模式空间&#xff08;pattern space&#xff09;是一块活跃的缓冲区&#xff0c;在sed编辑器执行命令时保存着待检查的文本&#xff0c;但它并不是sed编辑器保存文本的唯一空间。sed编辑器还有另一块称作保留空间&#xff08;hold space&#xff0…

【深度学习】BERT是什么?怎么玩的?

RNN 也是一种Seq2Seq网络 这种RNN就不能并行运算&#xff0c;且对于长句子会造成损失遗忘或者梯度爆炸 Transfomer Transformer由且仅由self-Attenion和Feed Forward Neural Network组成。一个基于Transformer的可训练的神经网络可以通过堆叠Transformer的形式进行搭建&…

美国大学特别重视的批判性思维,是如何培养出来的?

美国大学非常注重培养学生的批判性思维&#xff0c;爱因斯坦有一句名言&#xff1a;“大学教育的价值&#xff0c;不在于学习很多事实&#xff0c;而在于训练大脑会思考。” 批判性思维有两个典型特征&#xff1a;&#xff08;1&#xff09;批判性思维善于对通常被接受的结论提…

SpringMVC学习总结

SpringMVC简介 我们首先要了解MVC是什么 MVC是一种软件架构的思想&#xff0c;将软件按照模型、视图、控制器来划分 M&#xff1a;Model&#xff0c;模型层&#xff0c;指工程中的JavaBean&#xff0c;作用是处理数据 JavaBean分为两类&#xff1a; 一类称为实体类Bean&#xf…

oracle 19创建用户时出现“ORA-65096: invalid common user or role name”的错误

ORACLE 19命令 版本&#xff1a;Version 19.3.0.0.0 一、ORACLE 19创建用户命令 1、切换到oracle用户 [rootoracledb ~]# su - oracle Last login: Tue Jun 1 01:48:10 PDT 2021 on pts/5 2、以dba身份进入sql语句 [oracleoracledb ~]$ sqlplus "/as sysdba" …

2.rabbitMQ之交换机

1.交换机的作用 1.默认交换机会自动指定队列 2.之前一个信息必须被消费1次,现在的是一个消息可以被消费多次(发送到不同队列的前提下,正常情况下一个队列只能消费一次) 3.消息先发给交换机,然后交换机发给多个队列,可以达到多次消费的效果 如图mq3 2.交换机的类型 默认交换机…

【模块系列】DY-SV17F语音播放模块

前言 本文针对官方给的应用手册进行补充和加上个人理解。在官方的资料中已经介绍的很详细了&#xff0c;我就节选部分出来&#xff0c;基本认识模块就行了吧。本来还行自己介绍呢&#xff0c;没想到官方写这么详细了&#xff0c;也不知道介绍啥了&#xff0c;现在单纯的写为个人…

网络安全:钟馗之眼ZOOMEYE搜索引擎使用

网络安全&#xff1a;钟馗之眼ZOOMEYE搜索引擎 地址&#xff1a; 首页 - 网络空间测绘,网络安全,漏洞分析,动态测绘,钟馗之眼,时空测绘,赛博测绘 - ZoomEye("钟馗之眼")网络空间搜索引擎 zoomeye是针对互联网空间的搜索引擎&#xff0c;收录了互联网空间中的设备、…

103-Linux_I/O复用方法之epoll

I/O复用方法之epoll 一.epoll介绍二.epoll相关的函数1.epoll_create2.epoll_ctl3.epoll_wait 三.LT和ET模式1.LT模式2.ET模式 四.epoll实现TCP服务器1.代码(1)服务器端(2)客户端代码 2.运行结果截图 一.epoll介绍 epoll 是 Linux 特有的 I/O 复用函数。它在实现和使用上与 sel…

小程序swiper控件的使用

swiper实现左右滑动,以及tab点击,并且给swiper绑定下拉刷新事件 <view class"swiper-tab"><view class"start swiper-tab-list {{currentTab0 ? on : }}" data-current"0" catchtap"swichNav">私教课</view><vi…

sed进阶之创建sed实用工具

shell脚本编程系列 加倍行间距 sed $!G data2.txt保留空间的默认值是一个空行&#xff0c;通过G命令可以将保留空间内的内容附加到模式空间内容之后&#xff0c;但是最后一行不需要附加&#xff0c;所以通过排除命令!进行排除 对可能含有空行的文件加倍行间距 sed /^$/d;$!G …

c++11上篇

c11 1.C11简介2.列表初始化2.1 &#xff5b;&#xff5d;初始化2.2 std::initializer_list 3.变量类型推导3.1 auto3.2 decltype3.3 nullptr 4.范围for循环5.final与override6.智能指针7.新增加容器---静态数组array、forward_list以及unordered系列8.默认成员函数控制9.右值引…