java GC基础知识(一)
一、基础知识
1.1、java垃圾是什么?
没有引用指向的所有对象都是垃圾
1.2、怎样找到垃圾?
引用计数法和可达性分析法。
引用计数法:
当指向该对象的引用数为0时,该对象成为垃圾。但是无法解决几个对象之间相互引用的问题,会造成内存泄露
可达性分析法:
Root Searching(根可达算法),算法分析如下图:
其中根包括:
- 虚拟机栈(栈帧中的局部变量区,也叫做局部变量表)中引用的对象。
- 方法区中的类静态属性引用的对象。
- 方法区中常量引用的对象。
- 本地方法栈中JNI(Native方法)引用的对象。
1.3、垃圾回收的算法
1.3.1、标记清除法
算法相对简单,在存活对象比较多的情况下效率高(可以考虑运用到heap的老年区)。
但是需要两遍扫描(第一遍找出存活对象,第二遍扫描出垃圾对象并回收),效率偏低,容易产生碎片。
1.3.2、标记压缩
需要扫描两次,而且需要移动对象,效率偏低。
但不会产生碎片,方便对象分配,也不会产生内存减半。
1.3.3、拷贝
将内存分成两份,每次只使用一份,浪费空间;移动复制对象,需要调整对象的引用。但是只需要扫描一次。而且不会产生碎片。
适用于存活对象较少的情况(Eden空间)
二、JVM内存分代模型
2.1、堆内存逻辑分区
新生代不断产生新的对象,存活的对象比较少,适用于拷贝算法;老年代存活的对象比较多,适用于标记清除算法
新生代 + 老年代 + 永久代(1.7)Perm Generation/ 元数据区(1.8) Metaspace
2.2、一个对象的从出生到消亡。
我是一个普通的Java对象,我出生后没有通过逃匿分析,被分配到了Eden区,在Eden区我还看到和我长的很像的小兄弟,我们在Eden区中玩了挺长时间。有一天Eden区中的人实在是太多了,我就被迫去了Survivor区的“From”区,自从去了Survivor区,我就开始漂了,有时候在Survivor的“From”区,有时候在Survivor的“To”区,居无定所。直到我18岁的时候,爸爸说我成人了,该去社会上闯闯了。于是我就去了年老代那边,年老代里,人很多,并且年龄都挺大的,我在这里也认识了很多人。在年老代里,我生活了20年(每次GC加一岁),然后被回收。
2.3、GC的分类
- MinorGc/YGC:年轻代空间耗尽时触发,只回收年轻代空间。
- MajorGC/FullGC:老年代无法继续分配空间时触发,新生代、老年代同时进行回收。
2.4、对象什么时候进入老年代
- 超过 XX:MaxTenuringThreshold 指定的次数(YGC):只占四字节,所以最大是15,不可以调大
- Parallel Scavenge 默认15
- CMS 默认6
- G1 默认15
- 动态年龄
- Eden区+Survivor From -> Survivor To 的比例大于50%,把年龄最大的放入老年代