如何让System.gc()更快的工作

最近在在翻看java的Garbage Collection,即大名鼎鼎的垃圾收集器GC的相关资料,整理了一下头绪,和朋友们共勉之。

Java的GC机制大名远扬,它大幅提高了程序员开发效率,省去了在c#中要显式的释放每一块内存的麻烦。我们常听到的“内存泄漏”实际上就是指无用的内存没有被及时回收。例如你声明了一个变量,而该变量所在的主进程需要运行很长时间,那么就形成了局部上的“内存泄漏”。“内存泄漏”是相对来说的,即在内存资源紧张的时候,无用的内存没有被回收,系统就会面临内存泄漏的危险。

那现在说下什么样的情况会被GC回收,说简单点就是通路断掉的内存会被回收。可以看下面例子:

Object o1 = new Object();  
Object o2 = new Object();  
o2 = o1;  

o2=o1指明了这2个变量都指向了同一个对象,即使用了同一块内存区域,那么我们就说原o2申明的Object对象的那块内存会被GC回收,因为没有通路和它连通。

GC回收对程序员来说是透明的,要及时释放内存,最稳妥的方法就是在对象被使用完毕后,立即为该对象赋值为null,但是我们不知道什么时候这些无用资源会被回收,有什么办法可以显示执行吗?有的,就是显示调用System.gc();(该方法不保证立即会执行,因为不同的JVM使用不用算法来管理GC)。要让gc()达到立竿见影的效果,可以选择使用jdk1.2以来引入的4种对象引用类型上,废话不多说,看程序来说话:

import java.lang.ref.PhantomReference;  
import java.lang.ref.ReferenceQueue;  
import java.lang.ref.SoftReference;  
import java.lang.ref.WeakReference;  
  
class MyObject {  
    private String id;  
  
    public MyObject(String id) {  
		this.id = id;  
	}  
  
	public String toString() {  
		return id;  
	}  
  
	public void finalize() {  
		System.out.println("回收对象:" + id);  
	}  
}  
	  
public class TestReferences {  
	public static void main(String[] args) {  
		// 创建强引用  
		MyObject ref = new MyObject("Hard");  
		System.out.println(ref);  
		ref = null;  
		System.gc();  
		System.out.println(ref);  
		  
  
		// 创建软引用  
		SoftReference<myobject></myobject> softRef = new SoftReference<myobject></myobject>(  
				new MyObject("Soft"));  
		System.out.println(softRef.get());  
		System.gc();  
		System.out.println(softRef.get());  
  
		// 创建弱引用  
		WeakReference<myobject></myobject> weakRef = new WeakReference<myobject></myobject>(  
				new MyObject("Weak"));  
		System.out.println("before gc —— " + weakRef.get());  
		System.gc();  
		System.out.println("after gc —— " + weakRef.get());  
  
		// 创建虚引用  
		ReferenceQueue<myobject></myobject> rq = new ReferenceQueue<myobject></myobject>();  
		PhantomReference<myobject></myobject> phantomRef = new PhantomReference<myobject></myobject>(  
				new MyObject("Phantom"), rq);  
		System.out.println("before gc —— " + phantomRef.get());  
		System.gc();  
		System.out.println("after gc —— " + phantomRef.get());  
	}  
}

输出如下:

Hard
null
Soft
Soft
回收对象:Hard
before gc —— Weak
after gc —— null
回收对象:Weak
before gc —— null
after gc —— null
回收对象:Phantom

以上我们创建了4种引用,依次是:强引用、软引用、弱引用、虚引用。

强引用即我们普通使用的申明方式,对于该引用,只有显示的赋值为null,gc才会视为回收对象。

软引用(SoftReference)是只有内存不足时,gc才会将它视为回收对象。

弱引用(WeakReference)是无论当前内存是否满足,gc都会去回收它。

虚引用(PahntomReference)实际是可以理解成“子虚乌有”的引用,目的仅仅是结合引用关联队列(ReferenceQueue),实现对对象引用关系的跟踪。

在MyObject类中finalize方法中,我们让它在被回收时打印一句话出来,从输出结果来看,我们可以很容易的理解GC这4种对象引用的不同处理方式。从中我们可以得到结论,System.gc()可以对弱引用和虚引用达到立竿见影的效果。

好了以上一点小建议、想法,希望能对你有所帮助!

### 3.1 使用硬件位图(Hardware Bitmap)优化内存占用 从 Android 8.0(API 26)开始,系统引入了 **硬件位图(Hardware Bitmap)**,允许将图片数据存储在更高效的内存区域中,从而减少 Java Heap 的压力。硬件位图的像素数据并不占用 Java 堆内存,而是被放置在 Native 内存中,这种方式可以有效避免因大量图片加载而导致的 OOM 问题,并提升图像绘制效率。使用方式如下: ```java Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image); Bitmap hardwareBitmap = bitmap.copy(Bitmap.Config.HARDWARE, false); ``` 这种方式能够更好地与系统资源管理协同工作,从而减少 GC 的频率[^1]。 --- ### 3.2 使用 NativeAllocationRegistry 管理本地内存 Android 8.0 引入了 `NativeAllocationRegistry`,用于辅助回收 Native 内存。通过该机制,可以将 Bitmap 的像素数据分配在 Native 内存中,并与 Java 对象一起快速释放。这种方式不仅减轻了 Java 堆的压力,也提升了内存回收效率,从而减少频繁的 GC 操作[^1]。 --- ### 3.3 避免内存泄漏 内存泄漏是导致频繁 GC 和 OOM 的主要原因之一。例如,在 Activity 中启动了一个耗时线程,若在 Activity 销毁时线程仍在运行,可能导致该 Activity 无法被回收。为避免此类问题,应使用 `Application Context` 而非 `Activity Context`,并确保在组件销毁时及时释放资源,例如关闭 Cursor、取消异步任务等[^2]。 --- ### 3.4 合理管理对象生命周期 合理控制对象的创建与销毁,尤其是大对象(如 Bitmap、数据库连接等),应尽量复用对象或使用对象池机制。例如,使用 `LruCache` 来缓存图片资源,根据内存使用情况自动淘汰最近最少使用的对象: ```java int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); int cacheSize = maxMemory / 8; LruCache<String, Bitmap> memoryCache = new LruCache<>(cacheSize); ``` 这样可以有效减少内存分配和垃圾回收的频率[^3]。 --- ### 3.5 使用内存分析工具检测内存问题 Android 提供了多种内存分析工具,如 **Android Profiler** 和 **LeakCanary**,可以用于检测内存泄漏、监控内存使用趋势、分析对象分配情况等。通过这些工具可以更直观地发现内存瓶颈并进行优化。 --- ### 3.6 避免频繁触发 System.gc() 虽然 `System.gc()` 可以建议 JVM 执行垃圾回收,但其执行时机并不确定,且频繁调用可能影响应用性能。现代 Android 系统(尤其是 ART 运行时)已经能够根据内存压力自动调度 GC,因此不建议手动调用 `System.gc()` 来优化内存[^4]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值