大家好,我是小米,一个热爱技术分享的程序员。当天我想和大家一同聊一聊Java堆内存的划分以及回收算法。
什么是堆内存
堆内存如何划分空间
Java堆内存可以依据年龄和大小等要素启动划分。依据年龄,Java堆内存可以分为重生代和老年代两局部。
重生代中又可以分为Eden区、Survivor区From和Survivor区To三局部。其中,Eden区用于存储重生成的对象,Survivor区From和Survivor区To则用于存储在Eden区中存活上去的对象。
自动状况下,重生代和老年代的比例是1:2,即重生代占整个Java堆内存的1/3,老年代占2/3。而在重生代中,Eden区和Survivor区的比例是8:1:1,即Eden区占整个重生代的80%,Survivor区From和Survivor区To各占整个重生代的10%。
这两个比例的设置是为了统筹重生代和老年代的内存经常使用状况。假设重生代的比例过小,或许会造成频繁启动渣滓回收,而老年代的比例过大则或许会造成内存糜费。
咱们可以经过设置-Xmn命令来调整重生代的大小,经过-XX:NewRatio命令来调整重生代和老年代的比例。
为什么终身代被移除
在JDK1.8之前,Java虚构机中经常使用终身代来寄存一些静态数据和类信息等。然而由于终身代的内存经常使用和渣滓回收效率都不太理想,因此在JDK1.8中,终身代被移除了,并由元空间(Metaspace)来代替。
元空间是Java虚构机中寄存类元数据(Class Metadata)的区域,包含类的结构信息、字段、方法信息等。元空间的大小可以灵活地启动调整,当须要存储更多的类元数据时,元空间可以智能扩容。
相比于终身代,元空间的内存经常使用和渣滓回收效率都有了较大的优化。同时,由于元空间不再遭到终身代大小的限度,因此可以更好地顺应不同的运行场景。
设置元空间大小的命令是-XX:MaxMetaspaceSize。
标志-肃清算法(Mark-Sweep)
Java堆内存中的对象实例是灵活调配和回收的,Java虚构机提供了多种不同的内存回收算法来满足不同的内存治理需求。
标志-肃清算法是最基础的一种内存回收算法。其关键流程如下:
这种算法的缺陷是会发生内存碎片,造成内存应用率降低。
复制算法(Copying)
复制算法是将内存分为两局部,每次只经常使用其中一局部。当这局部内存用完后,将其中的生动对象复制到另一局部中,而后肃清这局部内存。
复制算法的好处是可以防止内存碎片,缺陷是须要消耗额外的内存空间。
复制算法关键用于重生代内存回收。
标志-整顿算法(Mark-Compact)
标志-整顿算法是将内存分为两局部,一局部存储生动对象,另一局部为未经常使用的内存空间。当内存空间无余时,先启动标志生动对象,而后将生动对象整顿到未经常使用的内存空间中,最后肃清未经常使用的内存空间。
标志-整顿算法可以防止内存碎片,但其缺陷是须要移动内存中的对象,因此效率较低。
标志-整顿算法关键用于老年代内存回收。
分代回收算法
分代回收算法是依据对象的生命周期将内存分为不同的代,每个代经常使用不同的内存回收算法。
重生代中普通经常使用复制算法,由于重生代中大局部对象的生命周期很短,因此这种算法的效率较高。而老年代中普通经常使用标志-整顿算法,由于老年代中存储的对象生命周期较长,因此算法能够有效地缩小渣滓回收的次数,提高Java运行的性能。
G1算法
G1算法是一种面向服务端运行的渣滓回收算法。它将堆内存划分为多个大小相等的区域(Region),每个区域既可以是重生代也可以是老年代。G1算法会依据运行程序的内存经常使用状况灵活地调整各个区域的大小。
在G1算法中,渣滓回收器不再依照重生代和老年代的划分启动渣滓回收,而是将整个堆空间一同思考。G1算法经常使用了相似分代回收算法的思维,将堆空间分为多个区域,每个区域的回收战略可以不同,这样就能够愈加灵敏地启动内存回收。
G1算法的好处是能够在保障渣滓回收效率的同时,防止了内存碎片的疑问。同时,由于G1算法能够灵活调整各个区域的大小,因此可以更好地顺应不同的运行场景。
综上所述,Java虚构机提供了多种不同的内存回收算法,每种算法都有其优缺陷和实用场景。在实践运行中,须要依据详细的运行场景来选用适合的渣滓回收算法,以便最大化地利用内存资源,提高运行程序的性能。
总结
本文详细引见了Java虚构机中堆内存的划分和回收算法。堆内存是Java虚构机中用于寄存对象的一块内存区域,Java程序中一切new进去的对象都会被寄存在堆内存中。为了愈加高效地利用内存资源,Java虚构机将堆内存划分为重生代和老年代,并针对不同的内存区域驳回不同的渣滓回收算法。
重生代中的渣滓回收算法关键有Serial、ParNew和G1算法。Serial算法是最基础的渣滓回收算法,驳回复线程启动渣滓回收。ParNew算法是Serial算法的多线程版本,在多核CPU上能够更好地利用配件资源,提高渣滓回收效率。G1算法是一种面向服务端运行的渣滓回收算法,能够更好地顺应不同的运行场景。
老年代中的渣滓回收算法关键有CMS和G1算法。CMS算法是一种基于标志-肃清算法的渣滓回收算法,驳回多线程启动渣滓回收,但存在碎片疑问。G1算规律是一种愈加灵敏的渣滓回收算法,能够防止内存碎片的疑问。
在实践运行中,须要依据详细的运行场景来选用适合的渣滓回收算法。同时,须要留意渣滓回收会对运行程序的性能发生影响,适度频繁的渣滓回收或许会造成运行程序的性能降低。因此,在设计和开发Java运行程序时,须要依据实践状况来正当设置内存空间的大小和渣滓回收算法的选用,以提高运行程序的性能和稳固性。