目录
垃圾回收
概述
垃圾回收功能是java中支持的功能,在其他的语言中也会存在自动的垃圾回收的功能(例如,python,C#,Ruby)等,垃圾回收机制主要解决的问题是,什么是垃圾,何时收集垃圾,如何收集垃圾这三个问题
什么是垃圾?
在java运行的过程中没有任何引用指向的对象就会被标记为垃圾
如果垃圾在内存中存放过多就会产生内存溢出的问题
为什么要进行垃圾回收?
为了防止垃圾过多将内存占满,出现内存溢出的问题,需要进行内存的清理
整理碎片化的内存空间,高效的使用内存
内存溢出与内存泄漏
内存溢出:在java中,如果内存空间不足,且GC也无法清理出更多的空间时就会产生内存溢出的问题
内存泄漏:在java中针对那些生命周期很长对象,长期占用着内存的这种现象就叫内存泄漏,比较多指已经不使用的对象却无法进行垃圾回收
例如:单例模式创建的对象,生命周期与应用程序的生命周期是一样长的
一些提供close()方法的资源未关闭,像数据库连接对象,IO流对象,网络连接对象
垃圾回收机制
自动的内存管理
优点:自动化的内存管理,降低内存溢出与内存泄漏的风险,可以减少程序员的压力,使程序员精力放在业务上
缺点:降低了程序员对内存管理的能力,出现内存相关的问题时更不易排查
垃圾回收标记阶段
标记阶段的目的是为了找出垃圾回收的对象
只有被标记为垃圾的对象才会被垃圾回收器进行回收
什么样的对象会被判定为垃圾对象呢?简单来说就是没有被引用的对象
判断的两种对象是否是垃圾对象有两种方式:引用计数算法与可达性分析算法
引用性分析算法
原理:引用性分析算法的原理是在对象中存储一个引用的计数属性,如果该对象被引用则更新这个属性的值,如果该属性的值为0则被标记为垃圾对象
优点:垃圾对象容易识别,判定的效率高,回收没有延迟性
缺点:需要维护一个属性增加时空的开销,无法解决循环引用的问题(有两个以上的对象互相引用,又没有其他对象引用这个循环就会出现这个问题),出现内存泄漏的问题
可达性分析算法
原理:会根据GCRoot(根对象)来自上向下的找到被引用的对象,根据被引用的对象再找到以该对象为节点,这个对象的引用对象,这样一个搜索的链条叫做引用链(Reference Chain),没有被引用链所关联的对象就会被标记为垃圾回收算法
优点:能够解决的循环引用的问题,防止内存泄漏的问题出现
缺点:回收的过程中需要有一个搜索的过程,造成时间上的开销
能够作为GCRoot的对象:
1.虚拟机栈内引用的对象
2.方法区内引用的对象
3.被synchronize引用的对象
4.虚拟机内部引用的对象,(例如基本类型的Class类对象,异常类对象,系统类加载器)
目前现代JVM使用的都是可达性分析算法
Finaliztion机制
在一个对象被标记为垃圾对象之后,不会立马对对象进行销毁,对象还会有一个机会进行复活或者进行最后的逻辑处理,在销毁前会调用一个回调方法finalize()
finalize()方法继承的自Object类,在Object类中的方法体中是空的,finalize()方法只允许调用一次
finalize