昨天我们分析解释了JVM虚拟机中的栈(stack)的工作流程和构成。大家看完应该对于栈有相对全面的了解。
今天我们就来解释第三部分,也是占据了JVM虚拟机中最大的一块内存空间的堆(heap)的工作原理和工作结构。
在上面的图中堆(heap)和明天我们要讲的方法区(method area)都用了另外一个颜色来标注。其实也就是拿来和前两天介绍的程序计数器和栈作个区别。他们的不同点是在于堆和方法区是所有线程都共享的内存区域。而程序计数器和栈是线程隔离的。
堆的介绍
在整体上的描述中,堆在JVM中是这样的一个区域:
堆是Java虚拟机所管理的最大的内存块,属于线程共享的内存区域。
堆的作用是存放对象实例。
在JVM规范中对于堆的描述是:所有的对象实例以及数组都要在堆上分配。但是随着JIT编译器的发展和逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术会导致一些微妙的变化发生,所有的对象都分配到堆上就不是那么绝对了。
堆是GC(垃圾回收)的主要区域。
关于堆中的垃圾回收
下面我们就几个角度来解释一下堆中的垃圾回收。
从内存回收的角度来看,现在的GC算法基本上都采用分代收集算法。因此堆可以细分为:新生代和老年代;再细致一点的有Eden(伊甸)空间、From Survivor(from幸存)空间、To空间等。
从内存分配的角度来看,线程共享的Java堆可能分划分出多个线程私有的分配缓冲区。
堆的存储都是与内容无关。无论哪个区域存储的都是对象实例,之所以进一步划分是为了更好的回收内存或者更好的分配内存。
根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。
OOM异常
当前主流JVM中的堆大小都是按照可扩展来实现的(通过-Xmx和-Xms控制)。如果在堆中没有内存来分配实例,并且也无法再进行扩展的时候,会抛出OutOfMemeryError异常。
以上就是堆的分析。各位如果有补充的可以留言交流。也希望各位不吝赐教。今天的内容就到这里了。明天还有对于JVM的后续介绍。可以透露一下,明天是对于另一块重要的功能:方法区的解释。希望大家能喜欢。
我的文章每天都会在头条号首发,然后第二天转发到简书中,希望有兴趣的朋友可以关注我的头条号:[Bug制造机]
(https://www.toutiao.com/c/user/51553105950/#mid=1582105392193550)。谢谢大家的支持。
网友评论