开网站供免费下载,建设网站南昌,郑州五合一网站建设,做网站不实名认证可以吗文章目录JVM 收集算法标记-清除算法标记-复制算法标记-整理算法JVM垃圾收集器Serial收集器ParNew收集器Parallel Scavenge /Parallel Old收集器CMS收集器Garbage First(G1)收集器元空间引用强引用软引用弱引用虚引用JVM 收集算法
前面我们了解了整个堆内存实际是以分代收集机制…
文章目录JVM 收集算法标记-清除算法标记-复制算法标记-整理算法JVM垃圾收集器Serial收集器ParNew收集器Parallel Scavenge /Parallel Old收集器CMS收集器Garbage First(G1)收集器元空间引用强引用软引用弱引用虚引用JVM 收集算法
前面我们了解了整个堆内存实际是以分代收集机制为主但还是没有讲到具体是怎么实现的那么具体的过程到底是怎么样来实现的呢我们来了解下
标记-清除算法 这个回收方法就是首先需要标记出需要回收的对象然后再依次回收掉被标记的对象或者是标记出所有不需要回收的对象只回收未标记的对象 虽然此方法非常简单但是缺点也是非常明显的首先如果内存中存在大量的对象那么可能就会存在大量的标记并且大规模进行清除。并且一次标记清除之后连续的内存空间可能会出现许许多多的空隙碎片化会导致连续内存空间利用率降低.
标记-复制算法 我们标记算法就是将堆的区域分成两块大小相同放入区域然后每次只会使用其中一块区域每当到垃圾回收的时候将需要回收的对象标记出来之后将没有标记的复制到另外一边区域最后将一次清空当前区域虽然复制浪费了一些时间但这样能够很好的解决对象大面积回收后造成的碎片化问题 这种算法就非常适用于新生代(因为新生代的回收效率极高一般不会留下太多的对象)的垃圾回收而我们之前所说的新生代Survivor区其实就是这个思路包括8:1:1的比例也正是为了对标记复制算法进行优化而采取的。
标记-整理算法 上述我们提到了复制算法此算法在新生区应用完全应用完全没有问题但如果用在老年区就显得很鸡肋因为老年区基本都是一些钉子户它不像新生区那样每次回收都会腾出大量空间对象才有机会进入到老年代所以老年代一般都是些钉子户可能一次GC后仍然存留很多对象。而标记复制算法会在GC后完整复制整个区域内容并且会折损50%的区域显然这并不适用于老年代。 那么我们能否这样在标记所有待回收对象之后不急着去进行回收操作而是将所有待回收的对象整齐排列在一段内存空间中而需要回收的对象全部往后丢这样前半部分的所有对象都是无需进行回收的而后半部分直接一次性清除即可。 虽然这样能保证内存空间充分使用并且也没有标记复制算法那么繁杂但是缺点也是显而易见的它的效率比前两者都低。甚至,由于需要修改对象在内存中的位置此时程序必须要暂停才可以在极端情况下可能会导致整个程序发生停顿 所以我们可以将标记清除算法和标记整理算法混合使用在内存空间还不是很凌乱的时候采用标记清除算法其实是没有多大问题的当内存空间凌乱到一定程度后我们可以进行一次标记整理算法。 JVM垃圾收集器
Serial收集器
该收集器是比较元老的一个收集器在较早的jdk是虚拟机新生代区域收集器的唯一选择这是一款单线程的垃圾收集器也就是说当开始进行垃圾回收的时候需要暂停所有的线程直到垃圾收集工作结束他的新生代收集算法采用的是标记复制法老年代采用的是标记整理法
ParNew收集器
这款垃圾收集器相当于是Serial收集器的多线程版本它能够支持多线程垃圾收集: 除了多线程支持以外其他内容基本与Seria收集器一致并且目前某些JVM默认的服务端模式新生代收集器就是使用的ParNew收集器。
Parallel Scavenge /Parallel Old收集器
Parallel Scavenge同样是一款面向新生代的垃圾收集器同样采用标记复制算法实现在JDK6时也推出了其老年代收集器Parallel Old采用标记整理算法实现: 与ParNew收集器不同的是它会自动衡量一个吞吐量并根据吞吐量来决定每次垃圾回收的时间这种自适应机制能够很好地权衡当前机器的性能根据性能选择最优方案。 目前JDK8采用的就是这种 Parallel Scavenge Barallel Old的垃圾回收方案。
CMS收集器
在JDK1.5HotSpot推出了一款在强交互应用中几乎可认为有划时代意义的垃圾收集器:CMS (Concurrent-Mark-Sweep)收集器这款收集器是HotSpot虚拟机中第一款真正意义上的并发(注意这里的并发和之前的并行是有区别的并发可以理解为同时运行用户线程和GC线程而并行可以理解为多条GC线程同时工作)收集器它第一次实现了让垃圾收集线程与用户线程同时工作。 它主要采用标记清除算法:
Garbage First(G1)收集器
我们知道我们的垃圾回收分为Minor GC 、Major GC和Full GC它们分别对应的是新生代老年代和整个堆内存的垃圾回收而G1收集器巧妙地绕过了这些约定它将整个Java堆划分成2048个大小相同的独立Region 块每个Region块的大小根据堆空间的实际大小而定整体被控制在1MB到32MB之间且都为2的N次幂。所有的Region 大小相同且在JVM的整个生命周期内不会发生改变。 那么分出这些Region有什么意义呢?每一个Region都可以根据需要自由决定扮演哪个角色(Eden、Survivor和老年代收集器会根据对应的角色采用不同的回收策略。此外G1收集器还存在一个Humongous区域它专门用于存放大对象一般认为大小超过了Region容量一半的对象为大对象这样新生代、老年代在物理上不再是一个连续的内存区域而是到处分布的。 它的回收过程与CMS大体类似: 初始化标记标记出对象能够关联到的对象 并发标记通过可达性分析递归整个堆里的对象图找出要回收的对象 最终标记对用户线程做一个短暂的暂停用于处理并发标记阶段漏标的那部分对象。 筛选回收制定回收计划 元空间 在JDK8之后我们堆里面就没有之前的永久代了随之产生的是一个叫做元空间的东西类的元信息被存储在元空间中元空间没有使用堆内存理论上系统可以使用的内存有多大元空间就有多大不会出现永久代存在时的内存溢出问题永久代就被完完全全的抛弃了 引用
强引用
在Java中如果变量是一个对象类型那么它实际上存放的是对象的引用类似于Object o new Object()这样的引用类型就是强引用 我们通过前面的学习可以明确如果方法中存在这样的强引用类型现在需要回收强引用所指向的对象那么要么此方法运行结束,要么引用连接断开否则被引用的对象是无法被判定为可回收的因为我们说不定后面还要使用它。 所以当JVM内存空间不足时JVM宁愿抛出OutOfMlemoryError使程序异常终止也不会靠随意回收具有强引用的“存活对象来解决内存不足的问题。 强引用写法 Object o new Object();
软引用
软引用不像强引用那样不可回收但一旦JVM内存不足的时候它会确保抛出异常之前清理掉软引用指向的对象 软引用写法SoftReference reference new SoftReference(new Object());
弱引用
弱引用的生命周期比软引用的还要短在进行垃圾回收的时候不管当前内存是否充足都会回收它的内存 弱引用写法 WeakReference reference new WeakReference(new Object());
虚引用
随时可能被回收 也就是说我们无论调用多少次get()方法得到的永远都是null因为虚引用本身就不算是个引用相当于这个对象不存在任何引用,并且只能使用带队列的构造方法以便对象被回收时接到通知。