本专栏专注分享大型Bat面试知识,后续会持续更新,喜欢的话麻烦点击一个关注
从Jvm内存模型中入手对于理解GC会有很大的帮助,不过这里只需要了解一个大概,说多了反而混淆视线。
Jvm(Java虚拟机)主要管理两种类型内存:堆和非堆。 堆是运行时数据区域,所有类实例和数组的内存均从此处分配。 非堆是JVM留给自己用的,包含方法区、JVM内部处理或优化所需的内存(如 JIT Compiler,Just-in-time Compiler,即时编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码。
简言之,Java程序内存主要(这里强调主要二字)分两部分,堆和非堆。大家一般new的对象和数组都是在堆中的,而GC主要回收的内存也是这块堆内存。
配一张示意图总结一下:
堆内存(Heap Memory): 存放Java对象 非堆内存(Non-Heap Memory): 存放类加载信息和其它meta-data 其它(Other): 存放JVM 自身代码等
一.堆内存模型
既然重点是堆内存,我们就再看看堆的内存模型。
堆内存由垃圾回收器的自动内存管理系统回收。 堆内存分为两大部分:新生代和老年代。比例为1:2。 老年代主要存放应用程序中生命周期长的存活对象。 新生代又分为三个部分:一个Eden区和两个Survivor区,比例为8:1:1。 Eden区存放新生的对象。 Survivor存放每次垃圾回收后存活的对象。
看晕了吧,关注这几个问题:
- 为什么要分新生代和老年代?
- 新生代为什么分一个Eden区和两个Survivor区?
- 一个Eden区和两个Survivor区的比例为什么是8:1:1?
现在还不能解释为什么,但这几个问题都是垃圾回收机制所采用的算法决定的。 所以问题转化为,是何种算法?为什么要采用此种算法?
二.可回收对象的判定
讲算法之前,我们先要搞清楚一个问题,什么样的对象是垃圾(无用对象),需要被回收? 目前市面