StackOverFlow vs OutOfMemeroy


StackOverFlow , 叫做 栈溢出, 从名字就可以看出来,明显跟 栈 这种数据结构有关。

我们知道 Java 是运行在 JVM 上的,JVM 又是基于栈 的虚拟机,这里为什么说JVM 是基于栈的呢,那就是因为,JVM 在运行的时候会给每一个Java线程分配独立的栈空间,或者说每个Java线程在创建的时候会向JVM申请自己的栈空间。所谓栈就是一个先进先出的数据结构,其实就是一块单独的空间,我们规定这个空间里的数据只能先进先出,后进后出而已。这个栈,是有一个个的栈帧组成的,你可以理解为,有一个空间,空间有一堆大小固定的格子,这格子你先不管盛的是啥,总之这些格子就组成了一个栈空间。每一个格子就代表这一个方法,格子的入栈和出栈就代表这一个方法的进入和返回。方法的执行就是对这个格子里面存储的空间进行读写的过程。栈帧里面存放着 局部变量表、操作数栈、动态链接、方法的返回地址。这里面的操作数栈就是方法运行过程中存放临时变量的地方,就是所谓 JVM 是基于栈 的虚拟机。那肯定有不是基于栈的JVM,比如 android 系统用到的 Dalvik 就是基于寄存器的,在这类JVM中也是一个线程单独分配一个栈空间,但是这个占空间里面没有操作数栈,而是几个寄存器,所有的操作结果都会写回对应的寄存器而不是栈。

StackOverFlow 栈溢出指的是JVM给线程分配的这个线程栈的溢出,注意操作数栈是不会溢出的,因为操作数栈的大小在你写完方法的时候就已经确定需要多少了。如果一个线程的线程栈,不停的被压栈,比如递归,你会发现最后一个栈帧进不去了,因为这个栈的大小是一定的,盛不开了,那就只能溢出了。

OutOfMemeroy,叫做内存不足,从名字就可以看出出来,明显是跟 内存 有关的。我们的程序总是要想操作系统申请空间的,如果申请空间的时候,操作系统告诉你空间不够了,那就叫 OutOfMemeroy。

所以对于内存不足的时候是抛出 栈溢出还是 内存不足,首先要看 内存不足的地方是不是栈,如果不是栈,那一定不会是栈溢出,一定是oom。如果是栈,那再看这个栈空间是不是支持动态扩展,如果不支持动态扩展,然后栈不够用了,那就是stackoverflow,如果支持动态扩展,但是在向操作系统申请的时候,操作系统说没有了,那也不叫栈溢出,而叫内存不足,如果支持动态扩展,但是已经扩展到分配的最大值了,但这时候栈还是不够用,那就叫栈溢出了。


评论