程序运行时,内存是如何分配的?

Jvm中的内存划分

JVM 中的内存可以划分为若干个不同的数据区域,主要分为:程序计数器、虚拟机栈、本地方法栈、堆、方法区

程序计数器

java本身是多线程的,当某一线程被CPU挂起后,需要记录程序执行的位置,这个时候就需要用到程序计数器。方便CPU重新执行此线程时,知道从哪行指令开始执行。这就是程序计数器的作用。

注意:
1、在JVM中,对于程序计数器没有规定任何OutOfMemoryError的情况。
2、线程私有的,每条线程内部都有一个私有程序计数器。它的生命周期随着线程的创建而创建,随着线程的结束而死亡。
3、当一个线程正在执行一个Java方法的时候,这个计数器记录的是正在执行的虚拟机字节码指令的地址。如果正在执行的是Native方法,这个计数器值则为空(Undefined)。

虚拟机栈

虚拟机栈是线程私有的,与线程的生命周期同步。在java的虚拟机规范中,定义了两种异常:
1、StackOverflowError:当线程请求栈深度超出虚拟机栈所允许的深度时抛出。
2、OutOfMemoryError:当Java虚拟机动态扩展到无法申请足够内存时抛出。

JVM是基于栈的解释器执行的,DVM是基于寄存器解释器执行的。

本地方法栈

本地方法栈和上面介绍的虚拟栈基本相同,只不过是针对本地(native)方法。在开发中如果涉及JNI可能接触本地方法栈多一些,在有些虚拟机的实现中已经将两个合二为一了(比如HotSpot)。

Java 堆(Heap)是 JVM所管理的内存中最大的一块,该区域唯一目的就是存放对象实例,几乎所有对象的实例都在堆里面分配,因此它也是Java垃圾收集器(GC)管理的主要区域,有时候也叫作“GC堆”)。同时它也是所有线程共享的内存区域,因此被分配在此区域的对象如果被多个线程访问的话,需要考虑线程安全问题。

方法区

方法区(Method Area)也是JVM规范里规定的一块运行时数据区。方法区主要是存储已经被 JVM 加载的类信息(版本、字段、方法、接口)、常量、静态变量、即时编译器编译后的代码和数据。该区域同堆一样,也是被各个线程共享的内存区域。

总结

JVM 的运行时内存结构中一共有两个“栈”和一个“堆”,分别是:Java虚拟机栈和本地方法栈,以及“GC堆”和方法区。除此之外还有一个程序计数器,但是我们开发者几乎不会用到这一部分。JVM内存中只有堆和方法区是线程共享的数据区域,其它区域都是线程私有的。并且程序计数器是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError 情况的区域。

参考

拉勾教育 - Android 工程师进阶34讲

坚持原创技术分享,您的支持将鼓励我继续创作!
0%