android 中 Runtime.gc、System.gc区别 & 对象引用关系
作者:访客发布时间:2023-12-26分类:程序开发学习浏览:93
导读:github.com/ccnio/Wareh…Runtime.gc、System.gc区别两者实现System.gc()内部调用Runtime.gc()//Runt...
github.com/ccnio/Wareh…
Runtime.gc、System.gc区别
两者实现
System.gc() 内部 调用 Runtime.gc()
// Runtime
public void gc() {
BlockGuard.getThreadPolicy().onExplicitGc();
nativeGc();
}
// System
public static void gc() {
boolean shouldRunGC;
synchronized (LOCK) {
shouldRunGC = justRanFinalization;
if (shouldRunGC) {
justRanFinalization = false;
} else {
runGC = true;
}
}
if (shouldRunGC) {
Runtime.getRuntime().gc();
}
}
leakcandary 触发 gc 使用的是 Runtime,注意其中的注释:
/**
* Default implementation of [GcTrigger].
*/
object Default : GcTrigger {
override fun runGc() {
// Code taken from AOSP FinalizationTest:
// System.gc() does not garbage collect every time. Runtime.gc() is
// more likely to perform a gc.
Runtime.getRuntime().gc()
enqueueReferences()
System.runFinalization() //注意这里的调用
}
}
结论
先说结论。
- 4.2.2源码: System.gc()的实现就是调用Runtime.getRuntime().gc(),所以两者是等价的。
- 5.0的源码不一样了:(看上述源码)单纯调用System.gc()是不会触发Runtime.getRuntime().gc()的。但是会把这次尝试纪录下来,等到下次调用System.runFinalization()时,会先执行这个Runtime.getRuntime().gc()。这样改后的影响至少有两点:
- 单纯调用System.gc()是不会触发Runtime.getRuntime().gc()的,直到调用了System.runFinalization()
- System.gc() -> System.gc() -> … -> System.gc() ->System.runFinalization(),最终只会调用一次Runtime.getRuntime().gc()
所以说只是单纯的调用System.gc(),在Android5.0以上什么也不会发生,可以这样调用:
- System.gc()和System.runFinalization()同时调用 或者
- 直接调用Runtime.getRuntime().gc()
验证
代码验证见下面引用介绍的中的 demo.
强、软、弱、虚引用
概念
注意措辞:引用、对象是两码事,val obj = Any(), obj 是引用,Any() 是对象。这里描述的四个引用其实用引用关系描述比较合适。比如:弱引用意思是,变量与对象的引用关系是弱引用,val obj = Weakerence(obj)。
- 弱引用:只具有弱引用的对象拥有更短暂的生命周期。gc 时一旦发现了只具有弱引用的对象(这里的含义参考下面的demo),不管当前内存空间足够与否,都会回收它的内存。
- 强引用:强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它
- 软引用:如果一个对象只具有软引用,则内存空间充足时,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。
- 虚引用:与其他几种引用都不同,虚引用并不会决定对象的生命周期。get方法返回null,不能获取值。虚引用主要用来跟踪对象被垃圾回收器回收的活动。但 leakcandary 中使用的是弱引用来跟踪对象被回收的
引用队列:软、弱、虚引用创建时可以指定一个引用队列 ReferenceQueue�,当引用的对象被回收时,这个引用(注意这里不是被引用指向的对象)会被加入到队列中。
代码验证
var obj: Any? = Any() // 这里是强引用关系。引用:obj, 对象: any
val weakReference = WeakReference(obj)
Log.d(TAG, "reference: value=${weakReference.get()}")
obj = null //这样 any 没有强引用了,只有 weakReference 的弱引用。
delay(1000)
Runtime.getRuntime().gc() // 手动触发垃圾回收, 使用 System.gc 不会生效
delay(2000) // 因为 any 只有弱引用, 所以 any 会被回收,weakReference.get 就返回空。
Log.d(TAG, "reference: after gc obj=${weakReference.get()}")
// 打印结果:
// reference: value=java.lang.Object@667e64b
// reference: after gc obj=null
// 虚引用验证
val queue = ReferenceQueue<Any>()
val reference = PhantomReference(obj!!, queue)
Log.d(TAG, "reference before: value=${reference.get()}, queue=${queue.poll()}, refer=$reference")
obj = null
Runtime.getRuntime().gc()
delay(1000)
Log.d(TAG, "reference after: ${reference.get()}, queue=${queue.poll()}")
//打印结果
//reference before: value=null, queue=null, refer=java.lang.ref.PhantomReference@e4c9c27
//reference after: null, queue=java.lang.ref.PhantomReference@e4c9c27
上述代码如果把 obj = null 注掉,any 对象因为还有 obj 的强引用,这样 weakReference.get 还能获取。
- 程序开发学习排行
-
- 1鸿蒙HarmonyOS:Web组件网页白屏检测
- 2HTTPS协议是安全传输,为啥还要再加密?
- 3HarmonyOS鸿蒙应用开发——数据持久化Preferences
- 4记解决MaterialButton背景颜色与设置值不同
- 5鸿蒙HarmonyOS实战-ArkUI组件(RelativeContainer)
- 6鸿蒙HarmonyOS实战-ArkUI组件(Stack)
- 7[Android][NDK][Cmake]一文搞懂Android项目中的Cmake
- 8Android广播如何解决Sending non-protected broadcast问题
- 9鸿蒙HarmonyOS实战-ArkUI组件(mediaquery)
- 最近发表
-
- WooCommerce最好的WordPress常用插件下载博客插件模块的相关产品
- 羊驼机器人最好的WordPress常用插件下载博客插件模块
- IP信息记录器最好的WordPress常用插件下载博客插件模块
- Linkly for WooCommerce最好的WordPress常用插件下载博客插件模块
- 元素聚合器Forms最好的WordPress常用插件下载博客插件模块
- Promaker Chat 最好的WordPress通用插件下载 博客插件模块
- 自动更新发布日期最好的WordPress常用插件下载博客插件模块
- WordPress官方最好的获取回复WordPress常用插件下载博客插件模块
- Img to rss最好的wordpress常用插件下载博客插件模块
- WPMozo为Elementor最好的WordPress常用插件下载博客插件模块添加精简版