JVM的主要作用
- 编译器把Java代码转换为字节码
- 类加载器把字节码文件加载到内存中,放在方法区中
- 命令解析器执行引擎将字节码指令翻译为底层系统指令,交给CPU执行
什么情况下会发生栈内存溢出
- 栈是线程私有的,他的生命周期与线程相同,每个方法在执行的时候都会创建一个栈帧,用来存储局部变量表,操作数栈,动态链接,方法出口等信息。局部变量表又包含基本数据类型,对象引用类型。如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常,方法递归调用产生这种结果。
- 如果Java虚拟机栈可以动态扩展,并且扩展的动作已经尝试过,但是无法申请到足够的内存去完成扩展,或者在新建立线程的时候没有足够的内存去创建对应的虚拟机栈,那么Java虚拟机将抛出一个OutOfMemory 异常。(线程启动过多)
堆和栈的区别
- 堆的物理地址分配是不连续的,性能较慢
- 栈保持先进先出的原则物理地址连续,性能较快
- 堆由于不连续,分配内存时需要在运行期确认,一般堆的大小大于栈
- 栈分配内存是在编译期确认的,大小固定
- 堆是多线程共享的
- 不同的方法执行时会在虚拟机栈中创建不同的栈帧,所以栈对于线程是私有的
- 堆主要用来存储对象实例和数组,栈主要用来存放局部变量表,操作数栈