Contents
  1. 1. JVM的内存主要分为3个区:
  2. 2. 本地方法栈和JVM栈是如何划分的
  3. 3. 数据库层面的堆和栈
  4. 4. 堆和栈的区别
  5. 5.  内存管理中的栈分配方法有什么特点?优缺点又是什么?

JVM的内存主要分为3个区:

  • 堆区(heap):只存对象本身(引用类型的数据),不存基本类型和对象的引用。JVM只有一个堆区,这个“堆”是动态内存分配意义上的堆–用于管理动态声明周期的内存区域。JVM的堆被同一个JVM实例中的所有Java线程共享,它通常由某种自动内存管理机制所管理–即“垃圾回收”。JVM规范并不强制要求JVM采用哪种GC算法。
  • 栈区(stack):栈中只保存基础数据类型的对象和对象引用。每个线程一个栈区,每个栈区中的而数据都是私有的,其他栈不能访问。栈内有帧(方法调用会生成帧栈)分三个部分:基本类型变量区,执行环境上下文,操作指令区
  • 方法区:又叫静态区,被所有线程共享。方法区包含所有的class和static变量。方法区包含的都是在整个程序中永远唯一的元素,如:class,static

本地方法栈和JVM栈是如何划分的

JVM规范写到:每个Java线程拥有自己的独立的JVM栈,也就是Java方法的调用栈。同时JVM规范为了允许native代码可以调用Java代码,以及允许Java代码调用native方法,还规定每个Java线程拥有自己的独立的native方法栈。都是JVM规范所规定的概念上的东西,并不是说具体的JVM实现真的要给每个Java线程开两个独立的栈。以Oracle JDK / OpenJDK的HotSpot VM为例,它使用所谓的“mixed stack”——在同一个调用栈里存放Java方法的栈帧与native方法的栈帧,所以每个Java线程其实只有一个调用栈,融合了JVM规范的JVM栈与native方法栈这俩概念。
如图:

数据库层面的堆和栈

数据结构里面。 stack,中文翻译为堆栈,其实指的是栈,这里讲的是数据结构的栈,不是内存分配里面的堆和栈。栈是先进后出的数据的结构,好比你碟子一个一个堆起来,最后放的那个是堆在最上面的。 栈数据结构比较简单。heap翻译为堆,是 一种有序的树。

堆和栈的区别

程序运行时候内存分配的策略

  • 静态存储分配:在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间。这种分配策略要求程序代码中不允许有可变数据结构(如可变数组),也不允许有嵌套或者递归的结构出现。因为它们都会导致编译程序无法计算准确的存储空间需求。
  • 栈式存储分配:也叫动态存储分配,和静态存储分配相反,栈就是暂时!在栈式存储方案中,存储的都是局部变量,临时变量,比如基本数据类型,对象引用……从内存的分配角度来看,因为存储的是基本的数据类型,编译器事先已经知道了类型的大小,故直接可以进行有效的内存分配,比如int,计算机是知道其范围的,所以直接由系统分配在栈中,无需程序自己去申请xxx内存!而引用类型,比如自己定义一个类,很明显这个类是不知道大小的,应该有程序自己来申请内存空间,所以由堆来分配!栈分配模式规定在运行中进入一个程序模块时,必须知道该程序模块所需的数据区大小,才能够为其分配内存。和我们在数据结构所熟知的栈一样,栈式存储分配按照先进后出的原则进行分配。
  • 堆式存储分配:则专门负责在编译时或运行时模块入口处都无法确定存储要求的数据结构的内存分配,比如可变长度串和对象实例。堆由大片的可利用块或空闲块组成,堆中的内存可以按照任意顺序分配和释放。

 因此我们断定:堆主要用来存放对象,栈主要是用来执行程序的。

栈可以这样理解:栈(Stack)是os在建立某个进程或者线程(在支持多线程的操作系统中是线程)时,为这个(进程)线程建立的存储区域,该区域具有先进后出的特性。
再说堆,每一个JVM的实例有且只有一个堆,这个唯一的堆被全局的线程共享!程序在运行中所创建的所有类实例或数组都放堆中,并由应用所有的线程共享。堆中的数据项位置没有固定的顺序,你可以以任何顺序插入和删除,因为他们没有“顶部”数据这一概念。

跟C/C++不同,Java中分配堆内存是自动化管理的(Java虚拟机的自动垃圾回收器来管理,缺点是,由于要在运行时动态分配内存,存取速度较慢)Java中所有对象的存储空间都是在堆中分配,但对象引用是在栈中分配,而堆中分配的内存才是实际的这个对象本身,栈中分配的内存只是一个指向这个对象的指针(引用)变量而已(变量的取值等于数组或对象在堆内存中的首地址)。而c++的堆内存管理,需要程序员手动管理的,new,delete运算符……

 内存管理中的栈分配方法有什么特点?优缺点又是什么?

首先想到就是该快内存FILO的特性,还有经过前面这么罗嗦的哔哔,又得出一个结论:栈中的数据可以共享。

  int a = 3;
  int b = 3;
  编译器先处理int a = 3; 会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3; 在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。这时,如果再令a=4; 那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4; 如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。

  优点:速度快,不用管理内存,缺点是太小,方法调用过度,容易内存溢出,还有栈就是暂时,数据有生命周期,属于临时存储。

Contents
  1. 1. JVM的内存主要分为3个区:
  2. 2. 本地方法栈和JVM栈是如何划分的
  3. 3. 数据库层面的堆和栈
  4. 4. 堆和栈的区别
  5. 5.  内存管理中的栈分配方法有什么特点?优缺点又是什么?