网站首页 > java教程 正文
JVM将内存分为堆内存和堆内存。每当我们声明新的变量和对象、调用新方法、声明一个字符串或执行这些类似操作时,JVM将会从“栈内存”或“堆空间”中指定这些操作的内存。
栈内存(Stack Memory)
Java中的栈内存用于静态内存分配和线程执行。方法的原始数据类型值和方法中引用对象(存在堆空间里)的引用。
对该区域内存的访问按照后进先出(Last-In-First-Out)顺序进行。每当我们调用一个新方法时,就会在堆顶部创建一个新块,其中包含该方法的值,如原始数据类型变量和对象的引用。
当方法完成执行时,其相应的栈的帧被清除,流程返回到调用方法,并为下一个方法腾出空间。
栈内存有下面的特性:
- 随着新方法的调用和返回,它会增长和缩小。
- 栈内部的变量仅在创建它们的方法运行时存在。
- 当方法执行完成时,它将自动分配并释放。
- 如果此内存已满,则Java会抛出java.lang.StackOverFlowError 错误。
- 与堆内存相比,访问此内存速度更快。
- 该内存是线程安全的,因为每个线程都在其自己的栈中操作。
- 可以使用-Xss JVM参数来设置栈内存的大小。
堆空间
堆空间用于Java对象在运行时的动态内存分配。新对象总是在堆空间中创建,对这些对象的引用存储在栈内存中。
这些对象具有全局访问权限,我们可以从程序的任何地方访问它们。
我们可以将这个内存模型分解成更小的部分,称为代。它们包括:
- 年轻代:这是所有新对象被分配和老化的地方。当此区域填满时会进行一次小垃圾回收。
- 老年代:这是长期存活对象的存储位置。当对象被存储在年轻代时,会设置一个对象年龄的阈值,当达到该阈值时,该对象就会移动到老年代。
- 永久代:它由运行时类和程序方法的JVM元数据组成。
堆空间有下面的特性:
- 它通过包括年轻代、老年代和永久代在内的复杂内存管理技术进行访问。
- 如果堆空间已满,Java会抛出java.lang.OutOfMemoryError 错误。
- 与堆栈不同,这种内存不会自动释放。需要垃圾回收器来释放未使用的对象,以保持内存使用效率。
- 与栈不同,堆不是线程安全的,并且需要通过适当地同步代码来保护。
- 可以使用-Xms好-Xmx JVM参数来设置堆内存的启动内存和最大内存的大小。
示例
现在让我们分析一段简单的Java代码:
class Person {
int id;
String name;
public Person(int id, String name) {
this.id = id;
this.name = name;
}
}
public class PersonBuilder {
private static Person buildPerson(int id, String name) {
return new Person(id, name);
}
public static void main(String[] args) {
int id = 23;
String name = "John";
Person person = null;
person = buildPerson(id, name);
}
}
让我们逐步分析:
- 当我们进入main() 方法时,会在栈内存中创建一个空间来存储该方法的基本数据类型和引用。
- 栈内存直接存储原始数据类型整数id的值。
- 在栈内存中创建类型为Person 的person 对象的引用变量,它指向堆内存中实际对象。
- 从main() 调用参数化的构造器Person(int, String) 将在先前的栈的上方分配更多内存。这将保存:
- 调用对象在栈内存中的this 对象引用。
- 栈内存中的原始数据值id 。
- 指向堆内存字符串池中实际字符串的String参数名称的引用变量。
- main()方法进一步调用buildPerson() 静态方法,这将在先前的栈内存之上进行内存分配。再次按照上述方式存储变量。
- 而新创建对象person (类型为Person )的所有实例变量都将被保存到堆内存中。
参考资料:
https://www.baeldung.com/java-stack-heap
https://www.digitalocean.com/community/tutorials/java-heap-space-vs-stack-memory
https://www.javatpoint.com/stack-vs-heap-java
猜你喜欢
- 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 JVM 内存结构(jvm内存结构及作用)
- 2024-11-12 「JVM系列」 从一到掌握JVM系列之Java虚拟机栈
- 2024-11-12 答读者问:Java 里的堆内存和栈内存是什么意思?
- 2024-11-12 Java中堆和栈的区别(java中堆和栈的区别在哪)
- 2024-11-12 一文读懂Java本地方法栈(本地方法栈jni)
你 发表评论:
欢迎- 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)
本文暂时没有评论,来添加一个吧(●'◡'●)