为了更高效的运行应用程序,JVM 抉择将内存划分为栈空间和堆空间。 每当咱们申明新变量和对象、调用新办法、申明 String 或执行相似操作时,JVM 都会在栈或堆空间外面操作指定内存。
在这篇文章外面,咱们将简要介绍 JVM 的内存模型以及它们的次要性能,而后咱们将介绍它们是如何存储在内存外面,以及会在哪里应用到它们。最初,咱们将分几个维度总结它们之间的次要区别。
1. 栈空间
JVM 中的栈空间用于动态内存调配和线程的执行。 它蕴含办法的原始值以及对象的援用。
对该内存的拜访是按后进先出 (LIFO) 程序进行的。每当咱们调用新办法时,都会在堆栈顶部创立一个新块,其中蕴含特定于该办法的值,例如原始变量和对对象的援用。
当办法实现执行时,其相应的堆栈帧将被刷新,流程返回到调用办法,这样空间就又可用于下一个办法运行。
1.1 栈空间的次要个性
栈空间的其余一些个性包含:
- 它随着新办法的调用和返回别离增长和放大。
- 堆栈中的变量只有在创立它们的办法正在运行时才存在。
- 当办法执行实现时,它会主动调配和开释。
- 如果此内存已满,Java 将抛出 java.lang.StackOverFlowError.
- 与堆内存相比,拜访此内存的速度更快。
- 该内存是线程平安的,因为每个线程都在本人的堆栈中运行。
2. 堆空间
堆空间用于 Java 对象在运行时的动态内存调配 。新对象总是在堆空间中创立,而这些对象的援用则存储在栈空间中。
这些对象具备全局拜访权限,咱们能够从应用程序中的任何地位拜访它们。
咱们能够将这个内存模型分解成更小的局部,称为世代,它们是:
- 新生代: 这是所有新对象被调配和老化的中央。填满时会产生 Minor GC。
- 老年代: 这是存储长期存活对象的中央。当对象存储在新生代时,会设置对象年龄的阈值,当达到该阈值时,对象会被挪动到老年代。
2.1 堆空间的次要个性
堆空间的其余一些个性包含:
- 它通过简单的内存治理技术拜访,包含新生代、老年代等等。
- 如果堆空间已满,Java 抛出 java.lang.OutOfMemoryError.
- 拜访这块内存比栈内存慢
- 与堆栈相比,此内存不会主动开释。它须要垃圾收集器来开释未应用的对象,以放弃内存应用的效率。
- 与堆栈不同,堆不是线程平安的,须要通过正确同步代码来爱护。
3. 内存调配示例
基于咱们目前所学的,让咱们通过剖析一个简略的 Java 代码来展现 JVM 如何治理内存:
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 参数 name 的援用变量将指向堆内存中字符串池中的理论字符串
- main 办法进一步调用了 buildPerson() 静态方法,其进一步调配将在前一个之上的栈空间中进行。这将再次以上述形式存储变量。
- 堆内存会存储新创建的 Person 类型的 person 的所有实例变量
理论在内存中的调配如下图:
4. 小结
让咱们疾速总结一下栈空间和堆空间的次要区别:
参数 | 栈空间 | 堆空间 |
---|---|---|
应用场景 | 在线程执行期间应用 | 整个应用程序在运行时应用堆空间 |
大小限度 | 栈空间有大小限度,具体取决于操作系统,通常小于堆空间 | 通常没有大小限度 |
存储内容 | 仅存储原始变量和在堆空间中创立的对象的援用 | 所有新创建的对象都存储在这里 |
存取程序 | 它应用后进先出 (LIFO) 内存调配零碎进行拜访 | 该内存是通过简单的内存治理技术拜访的,次要包含新生代和老年代。 |
生命周期 | 栈空间只在以后办法运行时才存在 | 只有利用程序运行,堆空间就存在 |
效率 | 与堆相比,调配速度要快得多 | 与堆栈相比调配更慢 |
调配和回收 | 当一个办法被调用和返回时,这个内存将被主动调配和回收 | 堆空间是在新对象创立时调配的,当它们不再被援用时将被回收 |
栈空间和堆空间是 Java 分配内存的两种根本形式,相熟它们的工作原理,将有利于咱们开发出高效运行的 Java 应用程序。
本文亦通过 NoOne’s Blog 发表,更多分享请关注公众号 NoOneNoOne