java JVM内存区域和对象创建,内存布局,访问

Java 虚拟机自动内存管理,不需要像C/C++为每一个 new 操作去写对应的 delete/free 操作,不容易出现内存泄漏和内存溢出。但把内存控制权交给 Java 虚拟机,一旦出现内存泄漏和溢出问题,如不了解虚拟机怎样使用内存,将很难排查错误。

JDK1.8内存分布

Java 虚拟机所管理的内存中最大的一块,Java 堆是所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。

字符串常量值:

JVM 为了提升性能和减少内存消耗针对字符串(String 类)专门开辟的一块区域,主要为了避免字符串的重复创建。

虚拟机栈

除了一些 Native 方法调用是通过本地方法栈实现的,其他所有的 Java 方法调用都是通过虚拟机栈实现。

本地方法栈

虚拟机栈为虚拟机执行 Java 方法 (也就是字节码)服务,而本地方法栈为虚拟机使用的 Native 方法服务。

程序计数器

程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。字节码解释器工作时通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等功能都需要依赖这个计数器来完成。

作用

  • 字节码解释器通过改变程序计数器来依次读取指令,从而实现代码的流程控制,如:顺序执行、选择、循环、异常处理。
  • 在多线程的情况下,程序计数器用于记录当前线程执行的位置,从而当线程被切换回来的时候能够知道该线程上次运行到哪儿了

运行时常量池

运行时常量池里放常量池表。常量池表存放编译期生成的各种字面量(Literal)和符号引用(Symbolic Reference。字面量包括整数、浮点数和字符串字面量。符号引用包括类符号引用、字段符号引用、方法符号引用、接口方法符号。

直接内存

一种特殊的内存缓冲区,不在 Java 堆或方法区中分配的,而是通过 JNI 的方式在本地内存上分配的。直接内存并不是虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用。而且也可能导致 OutOfMemoryError 错误出现。


HotSpot 虚拟机在 Java 堆中对象分配、布局和访问过程

第一步:类加载检查

虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载过、解析和初始化过。如果没有,那必须先执行相应的类加载过程。

第二步:分配内存

对象所需内存大小在类加载后可确定。分配方式有指针碰撞和空闲列表。

  • 指针碰撞:
    • 适用场合:堆内存规整(即没有内存碎片)的情况下。
    • 原理:用过的内存全部整合到一边,没有用过的内存放在另一边,中间有一个分界指针,只需要向着没用过的内存方向将该指针移动对象内存大小位置即可。
    • 使用该分配方式的 GC 收集器:Serial, ParNew
  • 空闲列表:
    • 适用场合:堆内存不规整的情况下。
    • 原理:虚拟机会维护一个列表,该列表中会记录哪些内存块是可用的,在分配的时候,找一块儿足够大的内存块儿来划分给对象实例,最后更新列表记录。
    • 使用该分配方式的 GC 收集器:CMS
  • 解决内存分配并发问题:CAS+失败重试 CAS 是乐观锁的一种实现方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。虚拟机采用 CAS 配上失败重试的方式保证更新操作的原子性。TLAB: 为每一个线程预先在 Eden 区分配一块儿内存,JVM 在给线程中的对象分配内存时,首先在 TLAB 分配,当对象大于 TLAB 中的剩余内存或 TLAB 的内存已用尽时,再采用上述的 CAS 进行内存分配

第三步:初始化零值

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

第四步:设置对象头

初始化零值完成之后,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的 GC 分代年龄等信息。 这些信息存放在对象头中。 另外,根据虚拟机当前运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。

第五步:执行init方法

在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了,但从 Java 程序的视角来看,对象创建才刚开始,<init> 方法还没有执行,所有的字段都还为零。所以一般来说,执行 new 指令之后会接着执行 <init> 方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生出来。


对象的内存布局

在 Hotspot 虚拟机中,每个对象的内存分为 :对象头实例数据对齐填充

对象头包括用于存储对象自身的运行时数据(哈希码、GC 分代年龄、锁状态标志等等),和类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针确定这个对象是哪个类的实例。

实例数据部分是对象真正存储的有效信息,即在程序中所定义的各种类型的字段内容。

对齐填充部分不是必然存在,无特别含义,仅起占位作用。 因为 Hotspot 虚拟机的自动内存管理系统要求对象起始地址必须是 8 字节的整数倍,即对象大小必须是 8 字节的整数倍。而对象头部分正好是 8 字节的倍数(1 倍或 2 倍),因此,当对象实例数据部分没有对齐时,需通过对齐填充来补全。

对象的访问定位

Java 通过栈上的 reference 数据操作堆上的具体对象。对象的访问方式由虚拟机实现确定,主流访问方式:使用句柄直接指针。

使用句柄:Java 堆划分出一块内存作为句柄池,reference 中存储对象的句柄地址,而句柄中包含对象实例数据与对象类型数据各自的具体地址信息。好处:reference 中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而 reference 本身不需要修改

直接指针:reference 中存储的直接就是对象的地址。好处:速度快,节省一次指针定位的时间开销

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

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

相关文章

软考89-上午题-【操作系统】-同步与互斥

一、进程间的通信 在多道程序环境的系统中存在多个可以并发执行的进程&#xff0c;故进程间必然存在资源共享&#xff08;互斥&#xff09;和相互合作&#xff08;同步&#xff09;的问题。进程通信是指各个进程交换信息的过程。 同步是合作进程间的直接制约问题&#xff0c;互…

LeetCode 21 / 100

目录 矩阵矩阵置零螺旋矩阵旋转图像搜索二维矩阵 II LeetCode 73. 矩阵置零 LeetCode 54. 螺旋矩阵 LeetCode 48. 旋转图像 LeetCode 240. 搜索二维矩阵 II 矩阵 矩阵置零 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为…

关于UDP协议

UDP协议是基于非连接的发送数据就是把数据包简单封装一下&#xff0c;然后从网卡发出去就可以&#xff0c;数据包之间没有状态上的联系&#xff0c;UDP处理方式简单&#xff0c;所以性能损耗非常少&#xff0c;对于CPU、内存资源的占用远小于TCP&#xff0c;但是对于网络传输过…

【OJ比赛日历】快周末了,不来一场比赛吗? #03.23-03.29 #16场

CompHub[1] 实时聚合多平台的数据类(Kaggle、天池…)和OJ类(Leetcode、牛客…&#xff09;比赛。本账号会推送最新的比赛消息&#xff0c;欢迎关注&#xff01; 以下信息仅供参考&#xff0c;以比赛官网为准 目录 2024-03-23&#xff08;周六&#xff09; #7场比赛2024-03-24…

74CMS人才系统 CVE-2024-2561 RCE复现

Fofa语法 app"骑士-74CMS" 复现步骤 前期准备 主页长这样 需要先会员注册&#xff0c;注册为招聘者 复现 将poc贴入修改登录的Cookie信息和Token 访问查看 微信公众号 扫一扫关注CatalyzeSec公众号 我们一起来从零开始学习网络安全 加入我们的星球&#xff0c;…

zabbix企业微信的告警媒介配置

简介&#xff1a; Zabbix企业微信告警媒介可用于向特定群组成员发送提醒通知。 前提条件&#xff1a; 完成Zabbix告警平台的搭建后&#xff0c;需将群机器人添加至告警提醒群中。 企业微信群聊——右上角三个点——添加群机器人 保存好产生的webhook地址&#xff08;注意&…

2024.3.20 使用maven打包jar文件和保存到本地仓库

2024.3.20 使用maven打包jar文件和保存到本地仓库 使用maven可以很方便地打包jar文件和导入jar文件&#xff0c;同时还可以将该文件保存在本地仓库重复调用。 使用maven打包jar文件和保存到本地仓库 package打包文件。 install导入本地仓库。 使用maven导入jar文件 点击“…

CVE-2023-49442 jeecg-formdemocontroller JNDI代码执行漏洞分析

漏洞描述 JEECG(J2EE Code Generation) 是开源的代码生成平台&#xff0c;目前官方已停止维护。JEECG 4.0及之前版本中&#xff0c;由于 /api 接口鉴权时未过滤路径遍历&#xff0c;攻击者可构造包含 ../ 的url绕过鉴权。攻击者可构造恶意请求利用 jeecgFormDemoController.do…

P1596 [USACO10OCT] Lake Counting S(找连通块数量)

题目描述 Due to recent rains, water has pooled in various places in Farmer Johns field, which is represented by a rectangle of N x M (1 < N < 100; 1 < M < 100) squares. Each square contains either water (W) or dry land (.). Farmer John would l…

基于springboot的反诈宣传平台

技术&#xff1a;springbootmysqlvue 一、系统背景 反欺诈平台可以对公交信息进行集中管理&#xff0c;可以真正避免传统管理的缺陷。反欺诈平台是一款运用软件开发技术设计实现的应用系统&#xff0c;在信息处理上可以达到快速的目的&#xff0c;不管是针对数据添加&#xff…

Vue3 进阶

Vue 进阶 前言 Vue3 入门文章地址&#xff1a;Vue3 入门 任务一 创建 Vite Vue3 单页应用 Vue 3 是一个流行的 JavaScript 前端框架&#xff0c;用于构建单页应用程序&#xff08;SPA&#xff09;。 下面是一些创建 Vue 3 单页应用程序的方式&#xff1a; Vue CLI&#…

NCV12711ADNR2G芯片PWM控制器中文资料规格书PDF数据手册引脚图图片价格功能

产品概述&#xff1a; NCV12711是一款固定频率、峰值电流模式PWM控制器&#xff0c;具有实施单端功率转换器拓扑结构所需的必要性能。这款器件工作电压范围4V至45V&#xff0c;无需辅助绕组&#xff0c;且位于热性能范围内。这款控制器包含一个可编程振荡器&#xff0c;能够在…

elasticsearch安装部署

elasticsearch部署 安装elasticsearch1.部署单点es1.1.创建网络1.2.加载镜像1.3.运行 2.部署kibana2.1.部署2.2.DevTools 3.安装IK分词器3.1.在线安装ik插件&#xff08;较慢&#xff09;3.2.离线安装ik插件&#xff08;推荐&#xff09;3.3 扩展词词典3.4 停用词词典 4.部署es…

Jmeter接口登录获取参数token报错问题解决方案

Jmeter接口登录时获取到的参数token一直在变的问题&#xff0c;导致运行时总是报错 解决方法如下&#xff1a; 1.新建一个GET的HTTP请求 2.添加正则表达式提取器 记得name"_token" value"(.?) 中间有一个空格&#xff0c;“_token”和value中间的空格&#xf…

Linux第81步_使用“互斥体”实现“互斥访问”共享资源

1、创建MyMutexLED目录 输入“cd /home/zgq/linux/Linux_Drivers/回车” 切换到“/home/zgq/linux/Linux_Drivers/”目录 输入“mkdir MyMutexLED回车”&#xff0c;创建“MyMutexLED”目录 输入“ls回车”查看“/home/zgq/linux/Linux_Drivers/”目录下的文件和文件夹 2、…

机器学习-可解释性机器学习:支持向量机与fastshap的可视化模型解析

一、引言 支持向量机(Support Vector Machine, SVM)作为一种经典的监督学习方法&#xff0c;在分类和回归问题中表现出色。其优点之一是生成的模型具有较好的泛化能力和可解释性&#xff0c;能够清晰地展示特征对于分类的重要性。 fastshap是一种用于快速计算SHAP值&#xff08…

进程创建,程序加载运行,以及进程终止,什么是僵尸进程,什么是孤儿进程

进程控制 创建进程&#xff0c;撤销进程&#xff0c;实现进程转换&#xff08;必须一气呵成&#xff0c;使用原语&#xff09; 原语不被中断是因为有关中断指令 创建进程 撤销进程 进程创建fork fork&#xff08;&#xff09;函数会创建一个子进程&#xff0c;子进程会返…

Uibot6.0 (RPA财务机器人师资培训第2天 )采购付款——网银付款机器人案例实战

训练网站&#xff1a;泓江科技 (lessonplan.cn)https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981(本博客中会有部分课程ppt截屏,如有侵权请及请及时与小北我取得联系~&#xff0…

网络编程day7

学生管理系统系统 #include <myhead.h> int do_add(sqlite3 *ppDb) {int add_numb0;char add_name[20]"";double add_score0;printf("请输入学号&#xff1a;");scanf("%d", &add_numb);printf("请输入姓名&#xff1a;");…

你要的个性化生信分析服务今天正式开启啦!定制你的专属解决方案!全程1v1答疑!

之前在 干货满满 | 给生信小白的入门小建议 | 掏心掏肺版 中有提到&#xff0c;如果小伙伴们真的想学好生信&#xff0c;那编程能力是必须要有的&#xff01;但是可能有些小伙伴们并没有那么多的时间从头开始学习编程&#xff0c;又或是希望有人指导或者协助完成生信分析工作&a…