1.为什么处理
清理无用信息释放内存
在C++中,对象所占用的内存,在程序运行完之前是无法被释放掉的,需要程序员编写代码,手动释放内存,这样不仅增加了程序员的工作量,在一定程度上,降低了整体效率。而在JAVA中,当没有对象引用指向原本分配给某个对象的内存时,该内存便会被视为垃圾。而JVM的垃圾回收机制,能在程序运行过程中,不断的清除垃圾,释放内存,从而大大增加了内存使用效率。
整理内存碎片
在对象的创建和垃圾清理的过程中会避免不了产生内存碎片,内存碎片是分配给对象的内存块之间的空闲内存洞,而碎片越多越不利于程序的运行,比如,当要创建一个以较大的对象时,虽然内存总剩余量是能够存储的,但是因为内存并不是一块连续的内存块而导致,无法创建,对我们来说是不利的。所以垃圾处理机制能帮助我们整理内存碎片,从而增加内存的使用率
2.处理什么
处理没有被GC-root说调用的“垃圾”对象
由上图可看出,Gc-root
引用了object1
,进而使得object2,3,4,5
都变成的存活对象,而object6
并没有被Gc-root引用,所以object6
被视为可回收对象,进而object7,8
也被视为可回收对象
GC-root:
虚拟机栈中引用的对象
当前正在被调用的方法里局部变量引用的对象,即虚拟机栈的局部变量表引用的对象
方法区中类静态属性引用的对象
简单来说就是类中使用static声明的引用类型字段
方法区中常量引用的对象
简单来说就是在类中使用final声明的引用类型字段
本地方法栈中引用的对象
本地方法栈中Native方法引用的对象
3.如何处理
3.1标记-清除法
执行过程:
当堆中的有效内存空间被耗尽时,程序将会停止,然后进行标记和清除工作。
标记:从根节点开始遍历,标记所有被引用的对象。
清除:Collector对堆内存从头到尾进行线性遍历,当遇到没有被标记的对象则将其回收
优点:实现简单
缺点:易产生内存碎片
3.2复制算法
复制算法会将内存分成等大 的两块内存,只是用其中一块,进行垃圾回收时,将存活的对象复制到另一块未被使用的,复制完全部存活对象之后,清除原内存块中的所有对象
优点:没有标记过程,实现简单,运行高效;不会出现内存碎片
缺点:内存空间减半
3.3标记-整理法
执行过程:
标记:从根节点开始遍历,标记出存活对象
整理:将所有存活对象压缩但内存的一端按序排放,之后清理边界以外的所有空间
优点:解决了内存碎片的问题,消除了复制算法中内存减半的高额代价
缺点:要进行移动操作,效率上是比复制算法要低的,移动对象的同时,如果对象被其他对象引用,则还需 要调整引用的地址
3.4分代收集算法
执行过程:
对象会优先进入Eden区,但Eden区的内存不足时,将会发起Minor GC,对Eden区和From区进行一次复制算法,将存活对象复制到To区,当Eden区的内存不足时,将会发起Minor GC,对Eden区和To区进行一次复制算法,将存活对象复制到From区以此类推。。当一个对象非常大时,将直接进入老年区,在新生代中经过数次清除之后仍然存活的对象将进入老年区,老年区通常使用标记整理算法以及标记清除算法
永久代:用来存储class类、常量、方法描述等。对永久代的回收主要回收两部分内容:废弃常量,无用类