jvm对象探究

news2024/10/2 12:33:17

hostpot虚拟机对象探究

jvm虚拟机创建对象的流程

ava虚拟机(JVM)创建对象的过程包括以下步骤:

  1. 类加载: 首先,JVM会检查对象的类是否已经被加载。如果该类还没有被加载,JVM会通过类加载器加载该类的字节码文件。
  2. 内存分配: 一旦类加载完成,JVM会在堆内存中为对象分配内存空间。Java的对象通常存储在堆中,堆是Java虚拟机管理的一块内存区域。
  3. 初始化零值: 在分配内存后,JVM会对对象进行初始化。这包括将对象的实例变量设置为默认的零值(数值类型为0,布尔类型为false,引用类型为null)。
  4. 构造方法调用: 接着,JVM会调用对象的构造方法(如果有的话)。构造方法负责完成对象的初始化工作,可以对实例变量进行赋值,执行其他必要的初始化操作。
  5. 对象引用: 一旦对象成功初始化,JVM将返回一个指向该对象的引用。这个引用可以被赋给类变量、实例变量、局部变量等,使得程序可以通过引用访问和操作这个对象。

需要注意的是,对象的内存分配和初始化是原子操作的,这意味着在对象初始化完成之前,其他线程无法看到或访问到这个对象。这有助于确保多线程环境

此外,Java虚拟机可能会对对象的内存分配和回收采取一些优化措施,如对象池、分代垃圾收集等,以提高内存利用率和程序性能。

java对象的内存分布

  • Java 对象头包括两个部分:Mark Word 和 Class Pointer,对于数组对象对象头还包括数组长度(Length),下面具体看一下每个部分:

    img

对象头

Mark Word

用于存储对象自身的运行时数据,如哈希码(HashCode)、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等,这部分数据的长度在 32 位和 64 位的虚拟机(未开启压缩指针)中分别为 32 个比特和 64 个比特。

包含两部分类信息:

  1. 存储对象自身运行时数据,哈希码,Gc分代年龄,锁状标志,线程持有的锁,偏向线程ID,偏向时间戳
  • 实例数据(Instance Data)
  • 对齐填充
Class Pointer

这部分是一个类型指针,即对象指向它的类型元数据的指针,Java 虚拟机通过这个指针来确定该对象是哪个类的实例。

并不是所有的虚拟机实现对象头都具有类型指针,这和对象的访问定位方式有关,主流的访问方式主要有使用句柄直接指针两种:

使用句柄的方式:Java 堆中将可能会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自具体的地址信息

直接指针的方式:Java 堆中对象的内存布局就必须考虑如何放置访问类型数据的相关信息,reference 中存储的直接就是对象地址,如果只是访问对象本身的话,就不需要多一次间接访问 的开销(HotSpot 虚拟机采用该方式,所以对象头中有类型指针用于存放对象结构的引用)

img

img

length

如果对象是一个 Java 数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通 Java 对象的元数据信息确定 Java 对象的大小,但是如果数组的长度是不确定的,将无法通过元数据中的信息推断出数组的大小。

实例数据

实例数据部分是对象真正存储的有效信息,即我们在程序代码里面所定义的各种类型的字段内容,无论是从父类继承下来的,还是在子类中定义的字段都必须记录起来。这部分的存储顺序会受到虚拟机分配策略参数(-XX:FieldsAllocationStyle参数)和字段在 Java 源码中定义顺序的影响。 HotSpot 虚拟机默认的分配顺序为 longs/doubles、ints、shorts/chars、bytes/booleans、oops(Ordinary Object Pointers,OOPs),从以上默认的分配策略中可以看到,相同宽度的字段总是被分配到一起存放,在满足这个前提条件的情况下,在父类中定义的变量会出现在子类之前。如果 HotSpot 虚拟机的 +XX:CompactFields 参数值为 true(默认就为 true),那子类之中较窄的变量也允许插入父类变量的空隙之中,以节省出一点点空间。

这里指的是子类在继承父类的字段后,把原本填充的空间放上小的字段类型数据

对齐填充

对象的第三部分是对齐填充,这并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。由于 HotSpot 虚拟机的自动内存管理系统要求对象起始地址必须是 8 字节的整数倍,换句话说就是任何对象的大小都必须是 8 字节的整数倍。对象头部分已经被精心设计成正好是 8 字节的倍数(1 倍或者 2 倍),因此,如果对象实例数据部分没有对齐的话,就需要通过对齐填充来补全。

垃圾收集(GC)器和内存分配策略

  • 什么是GC?

    GC 是 garbage collection 的缩写,意思是垃圾回收——把内存(特别是堆内存)中不再使用的空间释放掉;清理不再使用的对象。

  • 为什么要GC?

    堆内存是各个线程共享的空间,不能无节制的使用。服务器运行的时间通常都很长。累积的对象也会非常多。这些对象如果不做任何清理,任由它们数量不断累加,内存很快就会耗尽。所以GC就是要把不使用的对象都清理掉,把内存空间空出来,让项目可以持续运行下去。

  • 什么样的对象是垃圾对象?

    不再使用或获取不到的对象是垃圾对象。

  • 如何把垃圾对象找出来?

    办法1:引用计数法(不采用,不能解决循环引用问题)

    办法2:可达性分析(从GC Roots对象出发,不可达的对象就是要清理的对象)

  • 找到垃圾对象如何执行清理?

    具体的GC算法

对象已死:

在回收对象的时候 要确认对象不可能再被任何途径使用的对象(以下方法)

1.程序计数法

  • 引用计数法是在对象每一次被引用时,都给这个对象专属的『引用计数器』+1。
  • 当前引用被取消时,就给这个『引用计数器』-1。
  • 当前『引用计数器』为零时,表示这个对象不再被引用了,需要让GC回收。
  • 可是当对象之间存在交叉引用的时候,对象即使处于应该被回收的状态,也没法让『引用计数器』归零。

2.可达性分析法

核心原理:判断一个对象,是否存在从『堆外』到『堆内』的引用。

为了解决引用计数法的循环引用问题,Java 采用了可达性分析的方法。其实现原理是,将一系列"GCroot"对象作为搜索起点。如果在"GCroot"和一个对象之间没有可达的路径,则该对象被认为是不可访问的。

img

要注意的是,不可达对象不等价于可回收对象,不可达对象变为可回收对象至少要经过两次标记过程。两次标记后仍然是可回收对象,则将面临回收。

引用

jdk1.2之前:如何reference类型的数据中存储的数值代表的是另一块内存的其实地址,就称该reference数据是 代表某块内存,某个对象的引用

jdk1.2后:

  • 强引用:最传统的引用定义,只要强引用关系还存在,垃圾收集器就永远不会回收掉被引用的对象
  • 软引用:用来描述还有用,但是非必须的对象,只被弱引用关联的对象,在系统将要内存溢出前,会把这些对象列入回收范围之中,进行二次回收.如果这次回收还没有呢足够的内存,才会抛出内存溢出异常
  • 弱引用:用来描述那些非必要对象,比软引用更弱一点,被弱引用关联的对象只能生存到下一次垃圾收集发生为止,当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉被弱引用关联的对象
  • 虚引用:也称"幽灵引用"或者"幻影引用",它是最弱的一种引用关系作用是:在这个对象被回收掉 的时候收到一个系统通知

生存还是死亡

在可达性分析算法中判定为不可达的对象,也不是‘非死不可‘在清理之前会进行两次标记,如过没有发现可达链,则会被标记一次

随后进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法

回收方法区

主要是对常量池的回收和对类的卸载。

在大量使用反射、动态代理、CGLib 、动态生成 JSP 以及 OSGi 场景都需要虚拟机具备类卸载功能,以保证不会出现内存溢出

类的卸载条件:

  • 堆中不含有该类的任何实例
  • 该类的classloader被回收
  • 该类对应的class对象没有被任何地方所引用,即没有通过反射访问该类方法

不过满足也不一定被卸载,可以通过 -Xnoclassgc 参数来控制是否对类进行卸载。

垃圾回收算法

  1. 引用计数式垃圾收集
  2. 追踪式垃圾收集
1.标记-清除

将存活的对象标记,然后清除未标记的对象。

缺点:标记、清除效率不高,且会产生不连续的内存碎片,导致无法给大对象分配内存

在这里插入图片描述

2.标记-整理

所有存活对象都向一端移动,然后直接清理掉端边界外的对象。实现了内存连续

在这里插入图片描述

3.复制

将内存划分为两块,每次只使用其中一块,内存用完将存活的对象复制到另外上,然后进行清理。

HotSpot虚拟机中Eden和S区比例是:8:1:1,内存的利用率达到90%,如果每次回收有多于10%的存活对象,此时要借用老年代来存储放不下的对象

在这里插入图片描述

4分代收集

根据对象存活周期将内存划分为几块,不同区域采用不同算法。

一般堆分为新生代和老年代:新生代使用复制算法;老年代使用标记-清除或标记-整理算法。

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

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

相关文章

TCP服务器的演变过程:多进程实现一对多的TCP服务器

使用多进程实现一对多的TCP服务器 一、前言二、新增使用的fork()函数三、实现步骤四、完整代码五、TCP客户端5.1、自己实现一个TCP客户端5.2、Windows下可以使用NetAssist的网络助手工具 小结 一、前言 手把手教你从0开始编写TCP服务器程序,体验开局一块砖&#xf…

【C++】unordered_set/unordered_multiset/unordered_map/unordered_multimap

我们下面来学习C的另外两个容器:unordered_set和unordered_map 目录 一、unordered系列关联式容器 二、unordered_map 2.1 unordered_map的介绍 2.2 unordered_map的接口说明 2.2.1 unordered_map的构造 2.2.2 unordered_map的容量 2.2.3 unordered_map的迭…

室内设计品牌网站搭建的作用是什么

随着人们生活质量日益提升,对其自身的居住环境也有了较高要求,每个人审美不一样,无论自己居住的房屋还是公司办公/商场等场景都需要设计不同的内容,还有各种设施的摆放及类别等都有讲究,尤其对公司及商场等环境&#x…

动态规划算法练习题

45. 跳跃游戏 II 中等 2K 相关企业 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处: 0 < j < nums[i] i j &…

EasyExcel 导出文件的格式化

阿里开源的这个库&#xff0c;让 Excel 导出不再复杂&#xff08;既要能写&#xff0c;还要写的好看&#xff09; 之前聊了 EasyExcel 的内容导出&#xff0c;本文主要说一下导出文件的格式化&#xff0c;格式化包括工作表/单元格样式和内容格式化。毕竟&#xff0c;有时候还是…

【leetcode21】合并两个有序链表Java代码讲解

12.22 21. 合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]示例 2&#xff1a; 输入&#xff1a;l1 [], l2…

Appium Server 启动失败常见原因及解决办法

Error: listen EADDRINUSE: address already in use 0.0.0.0:4723 如下图&#xff1a; 错误原因&#xff1a;Appium 默认的4723端口被占用 解决办法&#xff1a; 出现该提示&#xff0c;有可能是 Appium Server 已启动&#xff0c;关闭已经启动的 Appium Server 即可。472…

音视频类App广告变现如何破局,最大化广告变现收益,让应用增收?

音视频App已然成为了我们日常获取、发布和交换信息的重要方式&#xff0c;在音视频行业不断的拓展中&#xff0c;用户的渗透率提升。 据数据显示&#xff0c;我国网络视听用户的规模已达9亿人次&#xff0c;网民使用率也突破了90%。庞大的市场规模和用户需求吸引了大批开发者和…

SRE - 监控建设

监控⽂档 随着信息技术的迅速发展及其在商业和工业环境中的广泛应用,系统的可靠性成为了组织的生存之本。Site Reliability Engineering(SRE)作为一种实践的结合体,广泛地用于确保和提升软件系统的可靠性。其中,它的一个重要组成部分是制定和监控服务的关键性能指标(Ser…

行为型设计模式(五):访问者模式 观察者模式

访问者模式 Visitor 1、什么是访问者模式 访问者模式允许定义一些不改变数据结构的前提下的操作。通过这种方式&#xff0c;可以在不修改元素类的情况下定义新的操作。访问者模式常用于对复杂对象结构进行操作&#xff0c;而又不希望在这些对象上破坏封装性。 2、为什么使用…

摄影企业网站搭建的作用是什么

几乎每个成年人都有一部手机&#xff0c;在互联网信息时代&#xff0c;手机的作用不言而喻&#xff0c;拍照/摄像成为了不少人经常会做的事&#xff0c;拍一张美美的照片发到社交圈赢得赞声&#xff0c;或是为以后留下回忆或发给自己在意的人&#xff0c;但这只限于生活记叙类图…

收集足够苹果的最小花园周长(LeetCode日记)

LeetCode-1954-收集足够苹果的最小花园周长 题目信息: 给你一个用无限二维网格表示的花园&#xff0c;每一个 整数坐标处都有一棵苹果树。整数坐标 ( i , j ) (i, j) (i,j) 处的苹果树有 ∣ i ∣ ∣ j ∣ |i| |j| ∣i∣∣j∣ 个苹果。 你将会买下正中心坐标是 ( 0 , 0 )…

免费使用谷歌Gemini模型学习LLM编程

虽然谷歌的Gemini大语言模型爆出很大的乌龙&#xff0c;但这不影响我们使用Gemini Pro来学习LLM编程。 目前Bard还没有全部切换为Gemini Pro模型&#xff0c;但是作为程序员&#xff0c;已经不需要等待&#xff0c;可以直接调用Gemini Pro的接口了。谷歌这次开发者优先的做法值…

12.23C语言 指针

& 地址运算符&#xff0c;用于取地址 /*注释内容*/ //注释一行 *的意思&#xff1a;1.算术运算符 2.用于指针声明int *ptr;表示这个变量是一个指针3.数组元素访问&#xff1a;在数组名后面使用 * 可以表示数组的起始地址。例如&#xff1a; int arr[5] {1, 2, 3, 4, 5…

WEB 3D技术 three.js 通过lil-gui 控制x y z轴数值 操作分组 设置布尔值控制 颜色材质控制

上文 WEB 3D技术 three.js 通过lil-gui管理公共事件中 我们用 lil-gui 处理了一下基础事件和按钮的管理 那么 本文 我们来具体说说它能做的其他事 我们先将基础代码改成这样 import ./style.css import * as THREE from "three"; //引入lil-gui import { GUI } fro…

题解:CF1914E-Game with Marbles

题解&#xff1a;CF1914E-Game with Marbles 事先说明一下&#xff0c;本题解不讲解简单数据范围的算法&#xff0c;因为复杂数据范围的就很简单。 这道题的大体意思是这样的&#xff1a;小A有颜色为i(i1~n)的小球a[i]个&#xff0c;小B有颜色为i(i1~n)的小球b[i]个。现在他们…

有关List的线程安全、高效读取:不变模式下的CopyOnWriteArrayList类、数据共享通道:BlockingQueue

有关List的线程安全 队列、链表之类的数据结构也是极常用的&#xff0c;几乎所有的应用程序都会与之相关。在java中&#xff0c; ArrayList和Vector都使用数组作为其内部实现。两者最大的不同在与Vector是线程安全的。 而ArrayList不是。此外LinkedList使用链表的数据结构实现…

ubuntu 22.04 安装mysql服务

完整内容&#xff1a; https://developer.aliyun.com/article/1260321 # 安装服务 sudo apt install mysql-server# 按向导设置root密码 sudo mysql_secure_installation# 使用设置的密码登录 sudo mysql -u root -p也可以使用工具登录&#xff0c;例如: navicat for mysql

掌握iText:轻松实现固定pdf模板的动态数据填充

推荐语 如果你在工作中需要处理大量的PDF表单&#xff0c;那么使用iText5实现固定PDF模板的动态数据填充&#xff0c;将是一种非常有效的方法。这篇技术文章详细介绍了如何使用iText5库来读取已有的PDF模板&#xff0c;并动态地填充表单数据&#xff0c;生成最终的表单文件。通…

虚拟机的下载、安装(模拟出服务器)

下载 vmware workstation&#xff08;收费的虚拟机&#xff09; 下载vbox 网址&#xff1a;Oracle VM VirtualBox&#xff08;免费的虚拟机&#xff09; 以下选择一个下载即可&#xff0c;建议下载vbox&#xff0c;因为是免费的。安装的时候默认下一步即可&#xff08;路径最好…