JVM运行时内存
从GC的角度,JVM堆分为:
-
新生代
- 1/3堆空间
新生代又分为
-
Eden区 : 8/10
- Java新创建的对象(除了大对象外)首先会被存放在Eden区。
- 当Eden区内存空间不足是会触发MinorGC
-
ServivorFrom区 : 1/10
-
Java新创建的大对象。
注:大对象的定义和具体的JVM版本、堆大小和垃圾回收策略有关,一般为2-128KB。
-
将上一次MinorGC是的幸存者作为这次MinorGC地被扫描者
-
-
ServivorTo区 : 1/10
- 保留上一次MinorGC是的幸存者
-
MinorGC:新生代的GC过程
采用复制算法实现
流程:
-
把在Eden区和ServivorFrom区中存活的对象复制到ServivorTo区
如果某对象的年龄达到老年代的标准(一般为15岁),则将其复制到老年代,同时把这些对象的年龄加1
如果ServivorTo内存不够或对象属于大对象,也直接复制到老年代
-
清空Eden和ServivorFrom区中的对象
-
将ServivorTo和ServivorFrom区互换
-
-
老年代
-
永久代
- 存储Class类、常量、方法描述等
- 1.8之后永久代已经被原属去去取代,放入本地内存
垃圾回收算法
确定垃圾的方法
-
引用计数法
- 对象添加/删除一个引用时,引用计数加/减1。当对象的引用计数为0,表示此刻该对象可以被回收
- 容易产生循环引用问题:两个对象相互引用,导致他们的引用一直存在,不能回收
-
可达性分析法
- 以一系列GC Roots的点作为起点向下搜索,在GC Roots和一个对象之间没有可达路径(引用链相连)时,称该对象是不可达的。在两次标记后该对象仍是不可达的,则将被垃圾收集器回收。
常用的垃圾回收算法
-
标记清除算法
-
过程:
- 标记:标记所有需要回收的对象
- 清除:清除可回收的对象并释放其所占用的内存空间
-
缺点:效率低、内存碎片多
由于标记清除算法在清理对象所占用的内存空间后并没有重新整理可用的内存空间,因此如果内存中可被回收的小对象居多,会引起内存碎片化问题,继而引起大对象无法或多连续可用空间的问题。
-
-
复制算法
-
过程:
- 将内存划分为两个大小相等的内存区域,区域1、区域2
- 新生成的对象都被存放在区域1中
- 在区域1内的对象存储满后对区域1进行一次标记,将标记后仍存活的对象全部复制到区域2。这时区域1将不存在任何存活的对象,直接清除整个区域1内的内存
-
缺点:浪费内存、可能会影响系统的运行效率
在系统中有大量长时间存活的对象时,这些对象将在区域1、2之间来回复制,影响系统的运行效率
-
有点:效率高(只在对象为’朝生夕死‘时)、易于实现
-
-
标记整理算法
结合了标记清除和复制算法
-
将内存划分为两个大小相等的内存区域
-
标记所有需要回收的对象
-
标记完成后将存活的对象移动到内存的另一端,然后清除该端的对象并释放内存
-
-
分代收集算法
针对不同的对象类型,采用不同的垃圾回收算法,该算法称为分代收集算法。