JAVASE进阶:内存原理剖析(1)——数组、方法、对象、this关键字的内存原理

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习
🌌上期文章:首期文章
📚订阅专栏:JAVASE进阶
希望文章对你们有所帮助

技术栈我已经基本上是学完了的,这段时间除了技术栈加班加点的学,还去接了别人的课设,接的最难的课设已经是涉及到了Redis、SpringCloud、ElasticSearch等。
除了大体上的后端开发技术栈我都学了,我还学了一些比较容易的比如mybatis-plus、nginx等等,但是都是速成的,暂时不做总结,为了将来的面试也是要去重新过一遍总结一遍的。
以前学习过的东西永远都是非常重要的基础:javase、Javaweb、MySQL,所以我会再去学一遍里面比较高级的用法、底层的原理,以及面试常考的题目。

内存原理剖析(数组、方法、对象、this关键字)

  • Java内存分配
  • 数组的内存图
  • 方法的基本内存原理
  • 对象的内存图
    • 一个对象的内存图
    • 多个对象的内存原理
    • 两个变量指向同一个对象的内存图
    • 基础数据类型和引用数据类型
  • this的内存原理

Java内存分配

每个软件运行的时候都会占用内存,而Java运行的时候,jvm会占用一块内存空间,为了更好的应用这一部分空间,jvm将其分为了五个部分:

1、栈:方法运行时使用的内存
2、堆:存储对象或者数组,new来创建的,都存储在堆内存
3、方法区:存储可以运行的class文件
4、本地方法栈
5、寄存器

在jdk7以前,方法区实际上是和堆放在一起的,真实环境下也是连续的一段物理空间,但是这种设定方式并不是太好,这在以后慢慢剖析,不是本章重点。

到了jdk8以后,取消了方法区,新增元空间,把原来方法区的多种功能进行了拆分,有的功能放到了堆中,有的功能放到了元空间中。

主要需要掌握的就是栈和堆,通过简单代码引入一下:
在这里插入图片描述
这一串代码并没有new关键字,所以执行起来根本不要用到堆,只需要用到栈:
在这里插入图片描述

数组的内存图

在某个方法执行的时候,可能会有new关键字,创建一个数组,new就会用到堆空间了,例如下面代码:
在这里插入图片描述
其执行的底层如下:
在这里插入图片描述
总之,new关键字后面的数组创建是在堆内存进行的,而返回给栈内存中的是这个数组的地址,当需要访问这个数组中的元素时,指定地址即可。

需要注意的是,int[] arr2 = {33, 44, 55}这一行代码是数组的静态初始化,虽然没有new,但是这实际上是简写,完整代码是int[] arr2 = new int[]{33, 44, 55},所以也是包含new关键字的,数组的创建依旧要到堆空间中。

有一种情况,两个数组指向了同一个空间的内存图:

int[] arr1 = {11, 22};
int[] arr2 = arr1;

这时候,栈内存有arr1和arr2的声明,而数组{11, 22}在堆内存中只有一个,也就是说int[] arr2 = arr1这条语句只是把arr1地址赋值给arr2,都指向了堆内存中的同一个数组。因此当arr1数组的元素改变的时候,查询arr2的时候能够发现它改变了。有点像之前学的指针,挺简单的不用过多解释了。

方法的基本内存原理

方法的执行是在栈进行的,栈具有后进先出的特点。所以需要注意一下方法嵌套时候方法调用的基本内存原理,如下代码:
在这里插入图片描述
执行的流程应该为:

1、执行main(),将main()压入栈
2、执行main()中的eat(),将eat()压入栈
3、执行eat()中的study(),将study()压入栈
4、执行study()中的输出语句,执行完毕,study()出栈
5、执行eat()中的输出语句
6、执行eat()中的sleep(),将sleep()压入栈
7、执行sleep()中的输出语句,执行完毕,sleep()出栈
8、eat()方法随之执行完毕,eat()出栈
9、main()结束,main()出栈

学过数据结构很容易懂,不用画图讲了。

对象的内存图

之前讲到,jdk8以后不再将方法区和堆合在一起了,而是拆开成元空间和堆。
元空间:字节码文件加载时进入的内存(.class文件)。
当我们执行Student s = new Student()时,底层会进行下列操作:

1、加载class文件
2、声明局部变量(等式左边)
3、在堆内存中开辟一个空间(等式右边)
4、默认初始化
5、显示初始化
6、构造方法初始化
7、将堆内存的地址值赋值给左边的局部变量

其中4、5、6是对第3步中开辟的空间进行的赋值操作:

默认初始化是对内存元素的默认赋值(int默认为0,String默认为null)
显示初始化是将Student类中成员变量的值赋值到堆空间中(如果有值)
构造方法初始化是将new Student()里面的参数赋值给堆空间,但这里无参构造可以忽略

一个对象的内存图

执行下列语句:
在这里插入图片描述
执行流程如下:

1、将StudentTest.class字节码文件存入方法区(元空间),并将main()进行临时存储
2、虚拟机自动调用程序主入口main(),main()就被加载到里面
3、将Student.class字节码文件加载到方法区中进行临时存储,记录了这个类中的所有信息(成员变量、成员方法)
4、中声明局部变量Student s
5、内存中开辟了一个空间,创建对象Student(),并会将方法区中临时存储的信息拷贝一份放在中,并进行默认初始化、显示初始化、构造方法初始化。除此之外,还会保存成员方法的地址。
6、将内存的地址值赋值给内存的局部变量Student s
7、栈内存执行相应操作,直到执行到study()方法,栈内存先根据地址找到了堆内存中的对象,堆内存根据成员方法的地址找到方法区中临时存储的成员方法。找到后,study()进入栈执行完就出栈
8、程序全部执行完毕后,栈内存中方法消失,方法中定义的局部变量也消失,也没有人再去用堆内存中的对象了,这个对象就会变成垃圾被jvm回收(垃圾回收机制)。

在这里插入图片描述

多个对象的内存原理

在这里插入图片描述
可以自行分析一下运行的流程,需要注意的一点是:Student()被new两次,堆内存中会创建2次对象,但方法区中不会重复将Student.class进行加载

两个变量指向同一个对象的内存图

Studnet stu1 = new Student();
Student stu2 = stu1;

和上述不同的是,堆内存中的Student只有一个,Student stu2 = stu1只是在栈内存中将地址进行传递而已。

基础数据类型和引用数据类型

通过上面例子应该很容易理解什么叫做引用数据类型了,Student s = new Student()这条语句中,栈空间中s被赋值了个地址,而不是真正的值,真正的值是引用了堆内存中的值,即为引用数据类型。
int a = 10这条语句,值直接就在栈内存中进行创建,即为基础数据类型。

this的内存原理

由于javase内部是遵循就近原则的,所以当我们这么写set方法的时候会出现问题:

String name; //成员变量
public void setName(String name){
	name = name;
}

set方法里的name都是局部变量,这样的语句并不能将值赋给成员变量,这会出现问题,正确的赋值语句为this.name = name,这就是this关键字的作用:区分局部变量和成员变量。

而this之所以能有这种作用,是因为this的本质为所在方法调用者的地址值

例如Student s = new Student(),再Student中的成员方法,方法体内若有this关键字,这个this代表的就是s的地址值(方法调用者),这样就会正确指向了成员变量而不是局部变量。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 828. 统计子串中的唯一字符

一开始想的是两次前缀和,发现自己蠢了 看了灵神的题解,类似于DP的思想 我们维护以每个字符串结尾的子字符串对答案的贡献,s[i]的贡献是多少?首先我们知道他需要自己单独一个串或者接在以s[i-1]结尾的那些字符串的后面&#xff0c…

【C++】类和对象(1)

上节我们学习了C入门的一些语法知识,这篇博客来学习类和this指针。 目录 面向过程和面向对象的初步认识 类的引入 类的定义 类的访问限定符及封装 访问限定符 封装 类的作用域 类的实例化 类对象大小 this指针 this指针特性 面向过程和面向对象的初步认识…

Transformer 自然语言处理(二)

原文:Natural Language Processing with Transformers 译者:飞龙 协议:CC BY-NC-SA 4.0 第五章:文本生成 基于 Transformer 的语言模型最令人不安的特点之一是它们生成的文本几乎无法与人类写的文本区分开。一个著名的例子是 Ope…

Redis 管道技术——Pipeline

背景 面试官:Redis 管道技术pipeline用过吗?为什么要用?解决什么问题?使用过程中应该注意什么? 我:一键三连,内心gg了,没听说过,也不知道用来干什么的,我只能…

C++ //练习 3.10 编写一段程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分。

C Primer(第5版) 练习 3.10 练习 3.10 编写一段程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分。 环境:Linux Ubuntu(云服务器) 工具:vim 代码块 /**…

Pycharm 关闭/退出烦人的Pytest模式

Pycharm 遇到:Run Python tests in ***.py ,但很多时候我们并不需要,真心烦人! 如何解决: 1 打开File-Settings (图片是新版界面,旧版同样操作) 2 Tools 中的Python Integrated Tools 在Tes…

[office] excel2010双向条形图制作 #经验分享#微信

excel2010双向条形图制作 本教程为大家介绍一下excel2010中excel2010双向条形图制作方法。 1.选中工作区域 2.点击插入-->图表,选择条形图 3.为美观可将中间竖线可去掉 4.方法是选中竖线,右击-->删除 5.接下来将图例靠上,选中图例,右击-->设置图例格式-->图例选项…

独立按键控制LED(基于51单片机)

师从江科大 独立按键 轻触按键: 相当于是一种电子开关,按下开关接通,松开开关断开,实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通好和断开 独立按键原理图: 注:没有按下独立按键是高电平&am…

对同一文件多次mmap

abstract 问&#xff1a;对同一个文件多次mmap&#xff0c;返回的地址相同吗? 答&#xff1a;不相同 code #ifdef __linux__#include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> …

1.D支撑线

从时间复杂度上来看&#xff0c;极点是O(n4)&#xff0c;极边是O(n3)&#xff0c;那么&#xff0c;还有没有可能使时间复杂度更小呢&#xff1f; 如上图所示将外部点X加入到原凸包&#xff0c;&#xff08;即S黄Vt蓝V所在的凸包&#xff09;那么可以观察到&#xff0c;将会组成…

【Java程序设计】【C00205】基于(JavaWeb+SSM)的商场停车服务管理系统(论文+PPT)

基于&#xff08;JavaWebSSM&#xff09;的商场停车服务管理系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于ssm的商场停车服务管理系统 本系统分为管理员和用户2个功能模块。 管理员&#xff1a;管理员进入主页面&…

网络协议与攻击模拟_12DNS协议及Windows部署DNS服务器

1、了解域名的结构 2、DNS查询过程 3、Windwos server部署DNS服务器 4、分析流量 实施DNS欺骗 再分析 一、DNS域名系统 1、DNS简介 DNS&#xff08;Domain Name system&#xff09;域名系统&#xff0c;作为将域名的IP地址的相互映射关系存放在一个分布式的数据库&#xff0c…

二分查找-迭代法

Go 算法 每天5道&#xff0c;开心快乐每一天 一点都不开心 哈哈哈哈哈哈 -2.1 day 1 1.22&#xff08;1.23 1.25 1.29&#xff09; 1.23 已复习 704. 二分查找 力扣题目链接 //左闭右开 func search(nums []int, target int) int { right : len(nums) left : 0; for le…

6个AI写作工具,让你的文字变得生动有力

写作是一项需要耐心和技巧的任务&#xff0c;对于许多人来说&#xff0c;写作可能是一项困难的挑战。然而&#xff0c;随着人工智能的发展&#xff0c;AI智能写作软件逐渐崭露头角&#xff0c;为我们提供了更加便捷和高效的写作体验。在本文中&#xff0c;我们将介绍几款好用的…

算法练习01——哈希部分双指针

目录 1. 两数之和(*)242. 有效的字母异位词(easy)49. 字母异位词分组(*)349. 两个数组的交集202. 快乐数(1.使用Set存哈希&#xff0c;2.快慢指针)454. 四数相加 II383. 赎金信15. 三数之和*(双指针)18. 四数之和*(双指针)128. 最长连续序列 1. 两数之和(*) https://leetcode.…

边缘计算网关在智能制造中有哪些应用?-天拓四方

在智能制造和工业生产环境中&#xff0c;数据已经成为新的生产要素&#xff0c;工业生产对实时性、灵活性和智能化也提出了更高的要求。而在这个过程中&#xff0c;边缘计算网关发挥着不可或缺的作用。它作为设备层与网络层之间的关键桥梁&#xff0c;确保了数据的实时、高效处…

STM32F407移植OpenHarmony笔记6

继上一篇笔记&#xff0c;编译好STM32的裸机程序&#xff0c;能点亮LED灯了。 下一步就是启动liteos_m内核了。 不过为了更好的调试代码&#xff0c;需要先把printf重定向到串口&#xff0c;基于gcc的printf重定向和Keil不一样。 直接新建printf.c&#xff0c;在里面重写printf…

基于 NOVATEK NT98530 Multiview Stitching 应用解决方案

感测技术近来于影像监控系统应用有了进一步的发展&#xff0c;多镜头的应用也与日俱增&#xff0c;如 AI 视觉感测会议相机&#xff0c;能满足远端多人聚会、远距教育训练的多元需求等&#xff0c;相关应用层面广泛涵盖了在生活中所面对的各种场景&#xff0c;带动更加可观的潜…

【安装指南】nodejs下载、安装与配置详细教程

目录 &#x1f33c;一、概述 &#x1f340;二、下载node.js &#x1f337;三、安装node.js &#x1f341;四、配置node.js &#x1f33c;一、概述 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时&#xff0c;用于构建可扩展的网络应用程序。Node.js 使用事件驱动、…

各品牌主板快速启动热键对照表及CMOS进入方法

各品牌主板快速启动热键对照表 主板品牌 启动按键 笔记本品牌 启动按键 主机品牌 启动按键 华硕主板 F8 联想笔记本 F12 联想台式机 F12 技嘉主板 F12 宏碁笔记本 F12 惠普台式机 F12 微星主板 F11 华硕笔记本 ESC 宏碁台式机 F12 梅捷主板 F9 惠普笔…