Java的堆,栈,方法区

关于java内存区域部分的堆,栈,方法区三个部分而言,我总结了一下大概为一下这张图。
Java的堆,栈,方法区
以下是我第一次初学堆,栈,方法区的一些心得,如有不足,希望各位大佬们指点一下
栈(Stack):

1.为什么栈要用来存储基本变量信息和对象引用

java虚拟机的基本架构就是采用栈来进行设计的。当一个程序需要运行的时候,由于要预先内存空间和运行的生命周期,所以需要进行指针的变动,来进行内存大小的分配。是的,由于这个操作会对程序的执行带来一定的不方便,所以一般栈被用来存放一些基本的变量类型或者引用对象的地址,而对于存储数据量较为庞大的java对象责备存储在了堆里面了。

2.为什么说栈的提取速度比堆要快?

小编我对于硬件部分也不是很理解,所以这里也只好从软件方面来分析,我认为的原因有以下几个:
1.栈里面的内存大小一般都是程序启动的时候由系统分配好的。
2.堆的内存大小需要在使用的时候才回去申请,而且每次对于内存大小的申请和归还都会比较消耗性能,开销较大。
3.cpu里面会有专门的寄存器来操作栈,堆里面都是使用间接寻址的方式来进行对象查找的,所以栈会快一些。

3.虚拟机栈里面为什么会有数据共享一说?

这个原因我们可以举一个例子来说吧:
假设有这么一段代码:
int j=10;
int k=10;
j=12;
对于这段简单的代码而言,虚拟机里面的栈又是如何处理的呢?其实比较简单的理解就是如下所示:
首先在栈里面会先查找是否存在一个区域存放有10,如果没有就创建一个区域存放10。然后将j引用到这个变量里面去。接着当程序执行到第二句的时候,虚拟机会先到栈里面去查找一下是否存在一个值为10的区域,如果有就直接让k指向10。所以基本如下图所示:
Java的堆,栈,方法区
当后期对于j变量的值进行修改为12以后,栈就会重复性的先去查找是否有12,如果没有开辟新的空间用于存储12,然后让j指向这个值
Java的堆,栈,方法区
这里面的10这个值,被k,j共同引用的过程就叫做数据共享。

4.栈里面到底存储了什么?

关于这个问题,我在《深入理解jvm&gc》这本书里面看到了一个比较好的解释,栈里面存储了很多小项,这里面我们称之为栈帧,这是一种数据结构用于存储方法的局部变量表,操作数栈,动态链接方法还有上下文数据等信息。
那么我们怎么来理解这个栈帧呢?每个栈帧里面都会存储有相应的一下内容:
1.局部变量表
2.操作数栈
3.栈帧数据区
这些东西第一次听说一般都会感觉比较陌生,那么我们来逐个逐个一一讲解:

局部变量表:
这里面的作用主要是存储一系列的变量信息,而且这些变量都是以数字数组的形式来存储的,一般而言byte,short,char,类型的数据在存储的时候会变为int类型,boolean类型也是存储为数字类型,long,double则是转换为双字节大小的控件存储在栈里面。

操作数栈:
关于这个小编也是有点不太了解,看了几篇博客之后也只是知道这个东西是可以将指令在栈里面进行push和pop操作,也是一个数字数组类型。

帧数据区:
主要作用有:保存有常量池里面的数据,正常方法的返回,异常处理等信息。
或许这么说,还是有些懵。我们可以这样简单化的来理解:
一个函数嵌套调用的次数多少一般都是由栈的大小来决定的。如果一个函数里面的参数过多,那么相关的局部变量也就越多,那么栈帧也就越大,同时循环调用的次数也就越少。
如果还想深入了解,可以使用jclasslib工具来查看相应的class文件中每个方法分配的最大局部变量区的容量。


堆(heap)

1.堆里面存放的内容主要还是new出来的对象和一些数组信息。

2.java的虚拟机不需要知道从堆内存里面存放多少空间大小的变量信息,也不需要知道每个对象的生命周期,所以一般程序运作的灵活性很高。

3.堆区里面存放了大量的对象很信息,所以也成为了gc重点回收的一个区域模块,所以当大量内存被占用的时候,gc的垃圾回收就会成为整个系统的性能瓶颈。于是随着jdk的不断更新,新的技术也对于jvm的内存分配这一块进行一定的优化改善,实现了off-heap。

好了,知道这些内容之后,基本简单的面试问题都可以干掉了,如果要深入了解的话可以从以下几个方面入手:
关于垃圾回收的原理和分类深入说明。
关于垃圾回收的原理?为什么要选择堆作为回收的重点对象?
什么是指针逃逸?如何对此进行优化?
不懂的东西还有很多,以后会专门写一些关于这方面的文章来进行深入分析。


静态方法区:
关于这个概念也可以称之为静态区,静态区和堆很相似,里面存放的信息也是线程共享的,它包含的信息如下图所示:
Java的堆,栈,方法区

方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。