当前位置: 首页 > news >正文

图解Java数组的内存分布

我们知道,访问数组元素要通过数组索引,如:

arr[0]

如果直接访问数组,比如:

int[] arr1 = {1};
System.out.println(arr1);

会发生什么呢?

在这里插入图片描述
打印的是一串奇怪的字符串:[I@16b98e56

这个字符串是Java在打印对象时的特殊输出,包含如下三部分信息:

  • 对象类型,如上图的[符号表示是数组类型,I表示整形数组
  • @是分隔符,没有实际意义
  • 16b98e56是堆内存地址,通过这个变量找到数组后,才能对其进行访问和修改

也就是说,数组变量存储的不是数组,而是一个地址,这个地址指向了哪里呢

要回答这个问题,首先要了解下Java的内存分布原理。

一,Java的内存分布

1,Java虚拟机内存划分

Java将虚拟机内存分为如下几个区域:

  • 本地方法栈
  • 寄存器
  • 虚拟机栈
  • 方法区/元空间

这样需要注意的是:从JDK8开始,Java取消了方法区,将方法区拆分到堆区、堆外区、元空间,增加一个元空间区,同时增加了堆外内存的使用。

JDK8前的内存分布:

在这里插入图片描述

JDK8的内存分布:

在这里插入图片描述

2,基本类型和引用类型的内存分布差异

特别来看下堆和栈,这是最为核心、重要的两个内存区域:
在这里插入图片描述

根据堆栈知识来理解下基本类型和引用类型的不同,这两种类型的变量值都存储在栈内存,但变量值本身的意义有较大的区别:

  • ①基本类型变量的值直接存储在栈内存,不涉及堆内存
  • ②引用类型变量的值在栈内存存储的是对象的地址,指向对象在堆内存的地址

基本类型变量的内存分布(仅涉及栈内存):

在这里插入图片描述

引用类型变量的内存分布(涉及栈和堆):

在这里插入图片描述

二,一个数组的内存分布

对于如下代码:

int[] arr = new int[2];
sout(arr);
sout(arr[0]);
sout(arr[1]);

逐行解释如上代码:

第一行代码声明并初始化一个数组arr,Jvm会做两件事:

  • ①在栈内存分配一块内存,存储数组对象地址
  • ②在堆内心分配一块内存,存储数组元素

第二行代码打印数组地址

第三行代码访问数组第一个元素,Jvm会根据栈内存中数组变量存储的地址,找到堆内存中数组对象,访问并读取第一个元素,然后打印

第四行代码和第三行作用相同,不同的是读取的是第二个元素

在这里插入图片描述

三,两个或多个不同数组的内存分布

当我们创建两个或两个以上的不同数组时,如图所示,会在栈内存中创建两个变量,这两个变量存储两个不同的堆内存地址,指向堆中不同的两个内存区域,存放着不同的两个数组对象:

在这里插入图片描述

当我们打印这两个数组变量时:

System.out.println(arr);
System.out.println(arr2);

输出的地址不相,分别是:[I@0x110fa7f48[I@0xbec966a

三,两个变量指向同一个数组的内存分布

int[] arr1 = {11,22};
int[] arr2 = arr1;
sout(arr1);
sout(arr2);
sout(arr1[0]);
sout(arr2[0]);
arr2 = new int[]{11, 22}

逐行解释如上代码:

第一行代码声明并初始化一个数组arr1,Jvm做两件事:

  • ①在栈内存分配一块内存,存储数组对象地址
  • ②在堆内心分配一块内存,存储数组元素

第二行代码声明并初始化一个数组arr2,Jvm做两件事:

  • ①在栈内存分配一块内存
  • ②将arr1变量的值复制给arr2

此时,变量arr1和arr2指向了同一块堆内存

在这里插入图片描述

执行第三行第四行代码:

sout(arr1);
sout(arr2);

会打印两个一样的值:[I@0x0011

第五行代码访问数组arr1第一个元素,Jvm会根据栈内存中数组变量存储的地址,找到堆内存中数组对象,访问并读取第一个元素,然后打印。

第六行代码访问数组arr2第一个元素,因为arr1arr2指向同一个数组,所以打印结果和第五行一致。

接下来,请大家思考,执行第七行代码arr2 = new int[]{11, 22}后,会出现什么情况呢?

尽管这个数组的元素个数、值都和arr1一致,但是Jvm还是会在堆区创建一个新的数组,并将arr2的值覆盖为新的数组对象的地址:

在这里插入图片描述

如果再次执行第三行第四行代码:

sout(arr1);
sout(arr2);

打印的结果就不再相同了,分别是[I@0x33bab[I@0x453fe

五,结论

  • ①数组变量分配在栈内存,存储的是对象地址,这个地址指向堆内存
  • ②数组对象(数组大小、所有数组元素)本身存储在堆内存中
  • ③访问和修改数组要通过数组变量存储的地址,找到数组对象,然后访问和修改其中的元素值
  • ④如果两个数组变量指向同一个数组对象,则通过变量访问的是同一个对象。如果之后其中一个数组指向另一个对象,通过这两个变量访问的就不再是同一个对象了

相关文章:

图解Java数组的内存分布

我们知道,访问数组元素要通过数组索引,如: arr[0]如果直接访问数组,比如: int[] arr1 {1}; System.out.println(arr1);会发生什么呢? 打印的是一串奇怪的字符串:[I16b98e56。 这个字符串是J…...

前端项目使用docker编译发版和gitlab-cicd发版方式

项目目录 app/ ├── container/ │ ├── init.sh │ ├── nginx.conf.template ├── src/ ├── .gitlab-ci.yml └── deploy.sh └── Dockerfile └── Makefilecontainer目录是放nginx的配置文件,给nginx镜像使用 .gitlab-ci.yml和Makefile是c…...

18kw 机架式液冷负载的使用方法有哪些?

机架式液冷负载是一种高效、节能的散热设备,广泛应用于数据中心、服务器房等场所。它通过将冷却液循环流动,将热量从负载设备带走,实现设备的稳定运行。以下是18kw机架式液冷负载的使用方法: 1. 安装前准备:在安装机架…...

Linux liloconfig命令教程:创建和配置LILO引导加载器(附实例详解和注意事项)

Linux liloconfig命令介绍 liloconfig(Linux Loader Configuration)是一个用于创建新的lilo.conf文件的简单程序。在创建新的配置文件后,你必须执行/sbin/lilo。liloconfig使用lilo.example.conf文件作为模板。 Linux liloconfig命令适用的…...

大厂程序员离职,开发一个盲盒小程序2万,一周开发完!

大家好,我是程序员小孟! 前面接了一个盲盒的小程序,主要的还是商城,盲盒的话只是其中的有一个活动。 现在的年轻人是真的会玩,越来越新的东西出来,越来越好玩的东西流行。 就像最近很火的地摊盲盒。 讲…...

自定义 Spring AOP 切面实战(鉴权、记录日志)

前言: 从事 Java 的小伙伴都知道 Spring AOP,也都知道 AOP 是面向切面编程,那你知道 AOP 在项目实战中怎么使用吗?本篇简单分享 Spring AOP 在项目中的实际使用。 AOP 知识储备传送门: 深入理解 Spring AOP 源码分析…...

JAVA面试题大全(九)

1、为什么要使用 spring? 方便解耦,便于开发支持aop编程声明式事务的支持方便程序的测试方便集成各种优秀的框架降低JavaEE API的使用难度 2、解释一下什么是 aop? AOP 是 Aspect-Oriented Programming 的缩写,中文翻译为“面向…...

React 组件三大核心之 ref

文章目录 用法React.createRef()useRef Hook 注意 ref 是 React 中的一个重要概念,它用于访问和操作 DOM 元素或者类组件实例。 在React中,ref 提供了一种方式,允许我们访问DOM节点或在render方法中创建的React元素。这对于执行DOM操作、读取…...

json 读写 python

目录 这里对json保存做了格式封装 调用代码: python json原始保存是所有json保存一行, 这里对json保存做了格式封装 import numpy as np class MyEncoder(json.JSONEncoder):def default(self, obj):if isinstance(obj, np.integer):return int(obj)…...

Docker快速部署Seata的TC服务以及微服务引入Seata教程

目录 一、使用docker部署Seata的TC服务 1、拉取TC服务镜像 2、创建并运行容器 ​3、修改配置文件 4、在Nacos中添加TC服务的配置 5、重启TC服务 二、微服务集成Seata 1、引入依赖 2、修改配置文件 Seata是阿里的一个开源的分布式事务解决方案,能够为分布…...

我的第一个JAVA程序IDEA版

目录 第一步 新建一个空项目第二步 新建模块第三步 新建包第四步 新建类第五步 新建main方法 第一步 新建一个空项目 第二步 新建模块 第三步 新建包 第四步 新建类 然后在包文件夹下新建类 第五步 新建main方法...

轻量SEO分析报告程序网站已开心去授权

轻量SEO分析报告程序网站已开心去授权,可以让你生成有洞察力的、 简洁的、易于理解的SEO报告,帮助你的网页排名和表现更好 网站源码免费下载地址抄笔记 (chaobiji.cn)https://chaobiji.cn/...

本机与华为云ping不通的问题

进入华为云控制台。依次选择:云服务器->点击服务器id->安全组->更改安全组->添加入方向规则,添加一个安全组规则(ICMP),详见下图 再次ping公网ip就可以ping通了 产生这一问题的原因是ping的协议基于ICMP…...

FastJSON2 > FastJSON 好在何处

FastJSON 是一种广泛使用的 JSON 解析库,其高性能和简单易用的特点受到开发者的喜爱。然而,随着应用场景的复杂化和安全要求的提高,FastJSON 逐渐暴露出一些问题。为了解决这些问题并进一步提升性能和安全性,阿里巴巴推出了 FastJ…...

7个常见的SQL慢查询问题及其解决方法

大家好,得益于摩尔定律,计算机性能已大幅提升,加上数据库的进步以及微服务所倡导的各种反模式设计,因此现在编写复杂SQL查询的机会越来越少。业界已经开始提倡不要进行专门的SQL优化,因为节省下来的资源并不足以抵消员…...

《Rust奇幻之旅:从Java和C++开启》第1章Hello world 1/5

讲动人的故事,写懂人的代码 很多程序员都在自学Rust。 🤕但Rust的学习曲线是真的陡,让人有点儿怵头。 程序员工作压力大,能用来自学新东西的时间简直就是凤毛麟角。 📕目前,在豆瓣上有7本Rust入门同类书。它们虽有高分评价,但仍存在不足。 首先,就是它们介绍的Rust新…...

将富文本编辑器中的H标签处理成树形结构,支持无限层级

做富文本编辑器时,需要将文本里的标题整理成树形数据, // 这里是数据结构 const data [{"id": "hkyrq2ndc-36yttda0lme00","text": "阿萨德阿萨德阿萨","level": 1,"depth": 1,},{"…...

探索移动云:我的ES与Kibana之旅

目录 引言: 如何免费体验移动云产品 登录并完成实名认证 选择试用ECS云主机 安全组配置 安装Elasticsearch和Kibana 安装Elasticsearch ​编辑安装kibana 测试结果 使用感觉 引言: 移动云技术产品的发展已经取得了巨大的进步。云数融合、A1、大…...

java 线程执行原理,java线程在jvm中执行流程

java 线程执行原理,java线程在jvm中执行流程 从jvm视角看java线程执行过程 ##首先thread.c注册jni函数 JNIEXPORT void JNICALL Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls) {(*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(…...

[Redis]基本全局命令

Redis存储方式介绍 在 Redis 中数据是以键值对的凡事存储的,键(Key)和值(Value)是基本的数据存储单元。以下是对 Redis 键值对的详细讲解: 键(Key): 类型:…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)

LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 题目描述解题思路Java代码 题目描述 题目链接&#xff1a;LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...

写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里

写一个shell脚本&#xff0c;把局域网内&#xff0c;把能ping通的IP和不能ping通的IP分类&#xff0c;并保存到两个文本文件里 脚本1 #!/bin/bash #定义变量 ip10.1.1 #循环去ping主机的IP for ((i1;i<10;i)) doping -c1 $ip.$i &>/dev/null[ $? -eq 0 ] &&am…...

2025.6.9总结(利与弊)

凡事都有两面性。在大厂上班也不例外。今天找开发定位问题&#xff0c;从一个接口人不断溯源到另一个 接口人。有时候&#xff0c;不知道是谁的责任填。将工作内容分的很细&#xff0c;每个人负责其中的一小块。我清楚的意识到&#xff0c;自己就是个可以随时替换的螺丝钉&…...