网站首页 > java教程 正文
在日常程序开发中,我们都知道Java程序都是运行在Java虚拟机上(JVM)的,程序中所有的方法、变量、常量、实例、静态存储都是由JVM在内存中进行分配的。
一、栈内存
主要用来存储线程执行过程中的局部变量(能否储存成员变量?),方法的返回值,以及方法调用上下文(对象的引用),是一种只能在一端(称为栈顶)对数据项进行插入和删除,它遵循先进后出的规则来存储数据。
疑问一:网上看了好多说栈数据可以共享。我的理解是:栈是线程私有的内存区域,每个线程都有一个栈,线程执行函数的时候,就会往这个栈里面压入一个栈帧,这个栈帧包含局部变量表和操作数栈,它是怎么做到数据共享的?
通俗一点来讲先进后出:比如我们买的羽毛球筒,工厂加工完成后,会一个一个将羽毛球压到筒中(最后压进的羽毛球会在最上部)(进栈),最后羽毛球达到我们手中后,我们会从上往下一个一个的取出(最上面的会先被我们给取出)(出栈)。这样说的话,大家应该能听的明白一点吧。
我们再用程序运行看下是否如我们上述描述的先进后出:
当我们在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,就会自动释放掉为该变量分配的内存空间(栈的作用域),它不会被GC管理。
栈内存中的数据(局部变量),没有默认初始化值,需要给赋值,不然在调用该变量的时候会提示
Initialize variable的错误。
二、堆内存
是在JVM启动时候自动分配的(看上一篇JVM内容),用来存放由new创建的对象和数组,用完后靠垃圾回收机制(GC)不定期自动销毁。
虚拟机中只有且只有一个堆,程序中所有线程都共享它,它的存取类型为管道类型,先进先出。
用例子简单说下栈和堆的关系(这方面可能理解不是很到位,大家若有意见可以下方评论共同探讨)
public static void main(String[] args) {
Car car = new Car();
car.wheel = "4";
Car car1 = new Car();
car1.seat = "12";
}
主函数先进栈,会在栈内存中开辟一个空间,存放car变量,同时在堆内存中也开辟一个空间,存放new Car()对象。我们知道内存存储数据的时候都是通过地址来体现的,所以会给Car这个实体分配一个内存地址:0x0011,把堆这个地址赋给栈中的car(引用变量),car就通过地址指向了Car这个实体。
在我们日常开发或面试的时候,经常会碰到java中equals和==的区别:
从上图,我们可以看到程序运行的结果:
1)对于==,int类型(8大基本数据类型)的比较结果输出为true,String类型的输出结果为false;
2)String类型通过equals比较结果为true.
m == n为true这个结果结果我们应该能容易理解,基本数据类型的变量在栈内存中存储的是实际的值,而a == b为false,是因为a和b是String类型的变量,是引用类型的变量,为非基本数据类型的变量,它存储的是对象的堆内存地址。a==b的比较实际上比较的是a和b对应的堆内存地址,它们指向的是不同对象。
equals操作表示的两个变量是否是对同一个对象的引用,即堆中的内容是否相同。
栈内存中能否储存成员变量?
不能,因为当对象创建出来,实体存在于堆,对象的成员变量已经在堆上分配空间,但对象里面的方法是没有出现的,只出现方法的声明,方法里面的局部变量并没有创建。等到对象调用此方法时,方法中的局部变量才会在栈中创建,所以,方法中的局部变量是在栈内的。
猜你喜欢
- 2024-11-12 本地方法栈、JVM栈、本地内存和JVM Heap的区别与关系
- 2024-11-12 Java基础之堆、栈、方法区、类加载器——JVM内存模型分析
- 2024-11-12 java之栈内存与堆内存(栈内存 和堆内存)
- 2024-11-12 深入了解Java虚拟机栈以及内存模型
- 2024-11-12 Java虚拟机栈区域(虚拟机栈描述的是java方法执行的内存模型)
- 2024-11-12 一文读懂Java的“栈内存”[Stack]和“堆空间”[Heap]
- 2024-11-12 JVM 内存结构(jvm内存结构及作用)
- 2024-11-12 「JVM系列」 从一到掌握JVM系列之Java虚拟机栈
- 2024-11-12 答读者问:Java 里的堆内存和栈内存是什么意思?
- 2024-11-12 Java中堆和栈的区别(java中堆和栈的区别在哪)
你 发表评论:
欢迎- 06-15Linux中如何通过Shell脚本来控制Spring Boot的Jar包启停服务?
- 06-15推荐一款超棒的SpringCloud 脚手架项目
- 06-15IDEA将项目打包成jar包(idea打包普通java项目)
- 06-15Spring Boot3 项目 jar 包打包成 Docker 镜像全攻略
- 06-15记录Dockerfile将jar包构建成部署所需的镜像
- 06-15项目基础部署汇总八---linux下xxl-job安装
- 06-15Spring Boot Jar 包秒变 Docker 镜像实现多环境部署
- 06-15终端执行 java -jar example.jar 时报错:“没有主清单属性” 的解决
- 最近发表
-
- Linux中如何通过Shell脚本来控制Spring Boot的Jar包启停服务?
- 推荐一款超棒的SpringCloud 脚手架项目
- IDEA将项目打包成jar包(idea打包普通java项目)
- Spring Boot3 项目 jar 包打包成 Docker 镜像全攻略
- 记录Dockerfile将jar包构建成部署所需的镜像
- 项目基础部署汇总八---linux下xxl-job安装
- Spring Boot Jar 包秒变 Docker 镜像实现多环境部署
- 终端执行 java -jar example.jar 时报错:“没有主清单属性” 的解决
- 如何将本地JAR文件添加到Maven项目中
- Java 类隔离应用:多 Jar 包支持(java接口隔离原则)
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)