目录
1.虚拟机类加载机制
2.JVM常见回收算法
2.1标记清除算法
2.2标记整理算法
2.3标记复制算法
3.分代垃圾回收机制
新生代收集
第一次垃圾回收
第二次垃圾回收
第N此垃圾回收
老年代收集
4.补充
Stop The World
Java的对象结构
1.虚拟机类加载机制
双亲委派模式:即加载器加载类时先把请求委托给自己的父类加载器执行,直到顶层的启动类加载器.
父类加载器能够完成加载则成功返回,不能则子类加载器才自己尝试加载.
优点:
- 避免类的重复加载
- 避免Java的核心API被篡改
2.JVM常见回收算法
常见的回收算法有三种:
- 标记清除算法
- 标记整理算法
- 标记复制算法
2.1标记清除算法
标记清除算法是最早出现的也是最基础的垃圾收集算法。
该算法可以分为两个阶段:标记---->清除
标记:把与 GC ROOT 没有关联的对象标记为垃圾
清除:把刚才标记的对象内存释放出来,然后放入空闲内存列表中,下次我们需要创建对象的时候就从空闲内存列表中进行使用。
缺点:
1、执行的效率极不稳定,当堆中有大量需要回收的对象这时候就需要做大量的标记和清除操作,标记和清除的执行效率随数量的增长而降低。
2、内存空间碎片化问题,标记、清除操作完之后会产生大量的不连续内存碎片,从而导致当程序中需要分配较大对象的时候无法找到足够的连续内存而不得不提前触发再一次垃圾收集动作。
2.2标记整理算法
该算法可以分为两个阶段:标记---->整理
标记:把与 GC ROOT 没有关联的对象标记为垃圾
整理:主要是解决标记清除算法出现的内存空间碎片化的问题,在清除垃圾的时候把内存整理好
标记整理算法在整理的过程中需要牵扯到对象的内存移动,必然这个效率肯定会比较低
2.3标记复制算法
该算法可以分为两个阶段:标记---->复制
标记:把与 GC ROOT 没有关联的对象标记为垃圾
复制:把不需要回收的对象复制到另一部分空闲的内存中,那么之前的那一块内存就都是垃圾,把之前整块都清空,然后交换位置,下次进行回收的时候进行同样的操作。
一般不会采用其中一种进行垃圾回收,而是采用分代回收机制
3.分代垃圾回收机制
现在大多商业jvm的垃圾收集器都遵循了分代收集的理论进行设计。
它把堆内存中的区域划分成两大块,一个叫新生代(Young Generation),一个叫老年代(Young Generation)两个区域,在新生代中每次垃圾收集时都发现有大量对象死去,然后每次回收后存活的少量对象逐步晋升到老年代中存放。
用完就能丢弃的对象就放在新生代中,长时间使用的对象就放在老年代中。这样就可以根据生命周期的不同特点使用不同的垃圾回收策略,老年代的垃圾回收很久才一次,新生代就会经常进行垃圾回收。
每个区域又分为三个部分:Eden(伊甸园)、幸存区 From、幸存区 To。
新生代收集
第一次垃圾回收
当我们创建一个对象的时候它最开始会创建在 Eden 中,之后会有越来越多的对象被创建在Eden 里,直至Eden内存被占用满这个时候就会出现一次垃圾回收,新生代的垃圾回收叫做 minor GC
minor GC流程就是先标记垃圾然后把垃圾清除,然后把存活的对象复制到幸存区To中并且会把幸存的对象寿命加1,并且会交换幸存区 From 和幸存区To,这就是第一次垃圾回收。
第二次垃圾回收
第一次垃圾回收完之后Eden区域又有剩余的内存可以使用了,这个时候我们又创建了很多新对象,并再一次把该区域占满。
触发垃圾回收,前部分都是一样,先标记清除,再复制到幸存区 To中,由于进行过交换这个时候的幸存区To就不是第一次垃圾回收的幸存区To了,而是第一次垃圾回收前的幸存区From。
再标记幸存区To中对象是否为垃圾,是垃圾就清除掉,不为垃圾就放入幸存区From中,并把对象寿命加1,再次交换幸存区 From 和幸存区To。
第N此垃圾回收
假设一个对象的寿命超过了一个域值了,就证明这个对象是比较有价值的,那么就会晋升到老年代中,新生代继续进行minor GC策略。
老年代收集
老年代垃圾收集Major GC或者称为Old GC,一般不会单独进行老年代垃圾收集,只有CMS收集器会进行单独收集老年代的行为。
老年代的收集算法不同于新生代,新生代主要采用复制算法,由于老年代的存过对象比较多整理起来或清除起来就会比较慢。这个要看各个厂商如何选择,一般为标记加清除算法或者标记加整理算法,效率上前者要大于后者
当新生代中对象年龄超过阈值时就会晋升到老年代中,最大寿命是15(因为每个对象的对象寿命都是保存在对象头中,保存寿命的大小是4bit,能标识的最大二进制为1111转换成十进制就是15) 但是不同的垃圾回收器对阈值的设定会不一样,当资源比较紧张时可能还没有到达15就会被放入至老年代中,所以15只是最大的阈值而不一定非要等到15才会晋升至老年代中。
当老年代中的对象不足以放下新生代晋升过来的对象时就会触发整理收集 Full GC
Full GC它会对整个Java堆和方法区进行垃圾回收,所以它的收集过程时间也会比较长,并且在收集过程中会出现 Stop The World。
4.补充
Stop The World
概念:进行垃圾回收的过程中,会涉及对象的移动。为了保证对象引用更新的正确性,必须暂停所有的用户线程,像这样的停顿,虚拟机设计者形象描述为「Stop The World」。也简称为STW。
不管是执行哪种垃圾回收机制都会触发 Stop The World
由于在执行垃圾回收的时候会进行内存对象的移动过程,这个过程中移动过的对象内存地址会发生改变,移动存活对象并更新所有引用这些对象的地方将会是一种极为负重的操作,而这种操作就必须暂停其它用户的线程或者说是暂停其它应用程序才能进行。
垃圾回收结束后才会恢复用户线程或者应用程序,新生代幸存的对象只有很少一部分所以新生代暂停时间较短,而老年代则相反暂停时间会较长。
Java的对象结构
Java对象由三个部分组成:对象头、实例数据、对齐填充。
对象头由两部分组成,
第一部分存储对象自身的运行时数据:哈希码、GC分代年龄、锁标识状态、 线程持有的锁、偏向线程ID(一般占32/64 bit)。
第二部分是指针类型,指向对象的类元数据类型(即对象代表哪个类)。如果是数组对象,则对象头中还有一部分用来记录数组长度。
实例数据用来存储对象真正的有效信息(包括父类继承下来的和自己定义的)
对齐填充:JVM要求对象起始地址必须是8字节的整数倍(8字节对齐)