Java虚拟机的堆、栈、堆栈如何去理解?
堆是堆(heap),栈是栈(stack),堆栈是栈。
栈中分配的是基本类型和自定义对象的引用。
堆中分配的是对象,也就是new出来的东西。 被所有线程共享。
方法区/静态区 存放的是类信息和static变量、常量。 被所有线程共享。
也可以这么理解:堆是用来存放对象的,栈是用来运行程序的。
堆:java的垃圾回收器会自动的回收这些不用的数据。缺点是由于要动态的分配内存,存储效率会比较的慢。
栈:栈的优势是存取效率比较快,仅次于寄存器,栈数据可以共享。但缺点是栈中的数据大小和生存期的固定的,缺乏灵活性。
一般每个方法的调用都会独立有一个栈来保存对象的引用变量,在方法返回后,栈会清空,当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。
JAVA的JVM的内存可分为3个区:堆(heap)、栈(stack)和方法区(method)
- 栈区:
- 每个线程包含一个栈区,栈中只保存方法中(不包括对象的成员变量)的基础数据类型和自定义对象的引用(不是对象),对象都存放在堆区中
- 每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
- 栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
- 堆区:
- 存储的全部是对象实例,每个对象都包含一个与之对应的class的信息(class信息存放在方法区)。
- jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身,几乎所有的对象实例和数组都在堆中分配。
- 方法区:
- 又叫静态区,跟堆一样,被所有的线程共享。它用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
这个“堆”并不是数据结构意义上的堆(Heap (data structure),一种有序的树),而是动态内存分配意义上的堆——用于管理动态生命周期的内存区域。
JVM规范让每个Java线程拥有自己的独立的JVM栈,也就是Java方法的调用栈。
JVM规范为了允许native代码可以调用Java代码,以及允许Java代码调用native方法,还规定每个Java线程拥有自己的独立的native方法栈。
并不是说具体的JVM实现真的要给每个Java线程开两个独立的栈。以Oracle JDK / OpenJDK的HotSpot VM为例,它使用所谓的“mixed stack”——在同一个调用栈里存放Java方法的栈帧与native方法的栈帧,所以每个Java线程其实只有一个调用栈,融合了JVM规范的JVM栈与native方法栈这俩概念。