`
anyanyway
  • 浏览: 13622 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

程序里到底需要不需要手动调用System.gc()

阅读更多
最近做的项目,同事喜欢在很多类里面加上一个release()之类的方法,并且在最后会调用一次System.gc(),说是这样可以有效的释放资源.在实际测试中,调用System.gc()的确可以回收一部分内存.但是,这个时候通常程序会明显感觉卡一下.到底应不应该手动调用System.gc()呢?我上网查了很多资料,其中一份是诺基亚论坛的<<Known Issues In The Nokia 6600 MIDP 2.0 Implementation>>,开头就是关于GC的:
Description:
Calling the System.gc() method results in extreme slowness and jamming. In Monty 1.0 VM, garbage collection is different and every time System.gc is called, the entire memory is really cleared. This is an extremely slow process!
Solution:
Do not call the System.gc method at all, or call the System.gc() garbage collecting method only in non-time-critical situations, such as screen transitions, state transitions, pause states, etc. If the System.gc() method is used, it is recommended to add a short delay (~20-50 ms) after the method call to ensure the sufficient time for the garbage collection, as in the following example:
System.gc();
Thread.sleep(delay); //delay = 20-50 ms

至少在6600的VM上,gc是会真的执行的,而不是"建议"执行.同事说这样至少可以防止OOME(OutOfMemoryException).其实经过实际测试,VM总是会在内存还剩10%~20%左右的时候调用自动GC,所以不会存在垃圾越堆越多.不过如果在内存资源紧缺的时候,加载大的资源还是会出现OOME.我的理解是:即时这个时候调用GC也无济于事.只能从根本上避免在内存到达峰值的时候加载大的资源.
另外,还有很多同事喜欢在一个对象不用的时候赋值null:
x=null;

据说这样是没有引用了,可以进行垃圾回收.我觉得如果是方法里面的对象属于年轻对象,VM是很快会知道该对象没有引用了的,不需要再手动赋值null,程序里到处是这样的语句,反而很丑陋.我反正从来没有因为忘记赋值null而导致程序崩溃过的,也没有因为赋值null而节约多少内存.
编码java时间不长,欢迎指正.
分享到:
评论
15 楼 flyingghost 2010-03-24  
鸟哥说的很到位。
gc原理大家都明白,完全是java描述的那样。
但实际编程中要不要调,什么时候调,取决于程序需求和虚拟机本身实现。
有的机器一次gc调用硬生生对应一次gc过程,完全没有所谓的消息通知。这时候调用越多机器越卡。
也有的机器自动gc性能非常差,以至于不依赖手动gc调用,内存基本得不到回收。
14 楼 chundonghu 2009-12-25  
LWUIT的主开发者推荐不要使用gc,而是使用WeakReference来代替,,不过这方面我没做过实验,有人做过使用WeakReference这方面的事吗?有数据的话就好说明了
13 楼 mingkg21 2009-12-23  
看情况吧。

有时有必要。

试过在游戏中释放资源时,没手动调用System.gc(),在下次导入资源时会内存溢出。手动调用System.gc(),不会出现内存溢出。

在内存溢出时试试手动调用System.gc()吧。也许可以解决。
12 楼 鸟哥哥 2009-12-23  
如果一个机器,一个对象x
这个机器只能容纳1.99999999个x对象
那么
X x = new X();
在用完x,想重新生成一个new X();
用x = new X();与用x = null;再用x = new X();
就非常有区别了,前者同时存在两个对象,内存爆了。后者不会。
所以用x = null;这个=null;在程序界都有用,都应该用,用都正确,而且用了才算是入了门,才算正确!
gc?用还是不用,不是你凭经验,凭wtk,凭模拟器,凭理论就确定的。
调gc无非是想催jvm回收,这必定消耗资源的,我用真机经验告诉你
Nokia s60 2nd 你催啊,你越催越慢,有时卡不动了!
而moto K1 V600等你不催啊,你不催内存就爆了!你必须常常催,不催就死了。
11 楼 imtrash 2009-09-26  
程序运行时,wtk自带的内存monitor中就可以看到自动回收的过程了,完全没必要手动system.gc()。
10 楼 Qaohao 2009-09-25  
system.gc运行级别是最低,一般在多线程编程中,自己手动调用gc,其实一点作用不起,因为处理机根本不给于搭理,除非是空闲时,手动调用了,反而可能会增加虚拟机的负荷。
9 楼 ningmenglovesoft 2009-09-24  
如果一个对象不用,想GC回收到他。直接将其引用指向null就可以了。在程序中根本没必要去显式调用System.gc();只会浪费更多资源。而且他完全不符合PMD规范
8 楼 esanone 2009-08-10  
除非系统安全性要求的高点,不然system.gc(),没必要我们coder新自去调用,不然和c++有怎么区别呢,至于将对象设为null看情况而定了,比较大的复杂的对象可以设为null,不过在方法里边好像没什么必要,一个方法执行over,对象变量的生命周性也就over了.
7 楼 luoyahu 2009-08-10  
softcat 写道
wayfarer 写道
java.lang.Object 写道
wayfarer 写道
TheMarine 写道
null值没必要,jvm自己清楚的很.


为什么没必要?你一个引用一直连着一个对象,kvm怎么知道你会不会再次使用这个对象。

如果一个方法里面的对象,就根本没有必要,如果是成员变量的话,你要换引用,直接赋另外一个就可以了,当然,你只是想置空一个的话,那也是可以显式的给null的


局部变量的生命周期就是方法的生命周期,方法结束了,局部变量自然就销毁了。如你所说,这个不用置null。
但是类变量还是需要置null的,因为这个类的对象本身是不会轻易销毁的。


当然,要制成NULL了,这样会加快KVM GC的效率。


赞成这一说法。
6 楼 anyanyway 2009-08-07  
我觉得置为null唯一的好处是在用完这个变量的时候,防止别人再去使用
5 楼 softcat 2009-08-07  
wayfarer 写道
java.lang.Object 写道
wayfarer 写道
TheMarine 写道
null值没必要,jvm自己清楚的很.


为什么没必要?你一个引用一直连着一个对象,kvm怎么知道你会不会再次使用这个对象。

如果一个方法里面的对象,就根本没有必要,如果是成员变量的话,你要换引用,直接赋另外一个就可以了,当然,你只是想置空一个的话,那也是可以显式的给null的


局部变量的生命周期就是方法的生命周期,方法结束了,局部变量自然就销毁了。如你所说,这个不用置null。
但是类变量还是需要置null的,因为这个类的对象本身是不会轻易销毁的。


当然,要制成NULL了,这样会加快KVM GC的效率。
4 楼 wayfarer 2009-08-06  
java.lang.Object 写道
wayfarer 写道
TheMarine 写道
null值没必要,jvm自己清楚的很.


为什么没必要?你一个引用一直连着一个对象,kvm怎么知道你会不会再次使用这个对象。

如果一个方法里面的对象,就根本没有必要,如果是成员变量的话,你要换引用,直接赋另外一个就可以了,当然,你只是想置空一个的话,那也是可以显式的给null的


局部变量的生命周期就是方法的生命周期,方法结束了,局部变量自然就销毁了。如你所说,这个不用置null。
但是类变量还是需要置null的,因为这个类的对象本身是不会轻易销毁的。
3 楼 java.lang.Object 2009-08-06  
wayfarer 写道
TheMarine 写道
null值没必要,jvm自己清楚的很.


为什么没必要?你一个引用一直连着一个对象,kvm怎么知道你会不会再次使用这个对象。

如果一个方法里面的对象,就根本没有必要,如果是成员变量的话,你要换引用,直接赋另外一个就可以了,当然,你只是想置空一个的话,那也是可以显式的给null的
2 楼 wayfarer 2009-08-06  
TheMarine 写道
null值没必要,jvm自己清楚的很.


为什么没必要?你一个引用一直连着一个对象,kvm怎么知道你会不会再次使用这个对象。
1 楼 TheMarine 2009-08-06  
null值没必要,jvm自己清楚的很.

相关推荐

    Android垃圾回收机制及程序优化System.gc

    二是当应用程序需要分配新的对象,但Java堆内存不足时,GC也会被调用。如果连续几次GC都无法满足内存需求,JVM会抛出“out of memory”错误,导致应用程序终止。 3. 减少GC开销的措施: - 避免显式调用`System.gc...

    jvm-full-gc.zip

    3. 显式调用System.gc():虽然不推荐,但手动调用会请求进行Full GC。 4. G1垃圾收集器的混合收集(Mixed GC)失败:G1在尝试进行混合收集时,如果无法满足目标空间需求,会退化为Full GC。 5. CMS(Concurrent Mark...

    C#中实现内存回收

    可以使用`System.GC.Collect()`方法来手动触发垃圾回收。然而,这并不推荐常规使用,因为频繁调用GC会影响程序性能,因为它会导致程序暂停执行,等待内存清理完成。 `MemoryCollectTest`程序可能包含以下关键部分:...

    2022年关于GC——Dotnet中Dispose的设计模式C语言教程.docx

    // 阻挡GC调用析构函数,因为已经手动调用Dispose System.GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { // 清理托管资源,例如关闭流或释放其他...

    调用Excel后的解决方法

    GC.Collect(); // 手动执行垃圾回收 ``` 3. **使用API手动结束进程**(如示例代码所示): - 当上述两种方法不能解决问题时,可以通过调用Windows API来强制结束Excel进程。 - 以下是具体实现步骤: 1. **获取...

    android内存管理

    1. **手动调用System.gc()**: 尽管可以尝试通过调用`System.gc()`来触发垃圾回收,但这并不总是最佳实践。调用此方法会导致当前线程暂停,等待GC完成,这可能会影响用户体验。而且,GC的工作方式是分批回收,可能...

    .net中清除EXCEL进程最有效的方法

    虽然`GC.Collect()`不是必需的,因为.NET框架的垃圾收集机制通常会在适当的时候自动回收不再使用的对象,但在这种情况下,由于Excel进程可能持有应用程序的引用,因此主动调用`GC.Collect()`有助于确保进程立即关闭...

    16_垃圾回收相关概念.pptx

    然而,需要注意的是,调用这个方法并不保证立即触发垃圾回收,因为JVM可能会根据自己的策略和需要来决定何时执行垃圾回收。 在描述中的例子中,尽管每次调用`System.gc()`时并未立刻看到垃圾回收的发生,但随后出现...

    Java的垃圾收集器(GC)参考.pdf

    6. **System.gc()的使用**:尽管可以调用`System.gc()`建议JVM进行垃圾收集,但不应过度依赖这个方法,因为垃圾收集器何时执行、是否执行是不确定的,过度调用可能会增加系统开销,影响性能。 7. **内存泄漏与内存...

    C#动态调用Web服务的3种方法

    objSVSGC = New WebSvs_GC.SVSGC(strWebSvsUrl) ' 调用WebService中的远程方法 strReturnValue = objSVSGC.HelloWorld() Catch ex As Exception End Try ``` #### 方法二:使用HttpClient 第二种方法是利用`...

    Java GC的副本.pptx

    同时,开发者也可以通过System.gc()等手段手动请求GC,但通常不推荐这样做,因为这可能导致性能下降。 3. **如何执行GC**:GC的执行过程包括标记、扫描和清理三个阶段。首先,GC会标记出所有活动对象;然后,扫描并...

    Java的垃圾收集器(GC)可用.pdf

    GC的执行是自动的,程序员不能直接控制何时进行垃圾收集,只能通过调用`System.gc()`方法发起一个回收请求,但这并不保证立即执行,且执行时间也无法预测。这是垃圾收集器的一个重要特性,也是其灵活性和不可预知性...

    JVM、GC详解及调优

    4. **GC触发条件**:内存分配达到阈值、手动触发、System.gc()调用等都可能导致GC启动。 5. **GC参数调整**:通过JVM参数可以调整GC行为,如-Xms、-Xmx设置堆大小,-XX:NewRatio设置新生代与老年代比例,-XX:...

    10常用类2.doc

    但请注意,垃圾回收是自动进行的,通常不需要手动调用。 4. `exec(String command)`:在一个独立的进程中执行指定的命令。例如,`exec("notepad.exe")`可以在Windows系统中打开记事本程序。 `Runtime`类的使用通常...

    Java 内存区域和GC机制

    - **GC触发条件**:当堆内存不足时,或者系统调用System.gc()时(不推荐)。 - **GC类型**:主要分为Minor GC(年轻代GC)、Major GC(老年代GC)和Full GC(全局GC)。 - **GC策略**:包括复制算法、标记-清除...

    c#CEXCEL关闭(解决无法关闭进程的问题)

    4. **强制垃圾回收**:尽管设置对象为null可以帮助垃圾回收机制释放资源,但有时可能需要手动调用GC.Collect()来强制执行垃圾回收,确保Excel进程被关闭。 ```csharp System.GC.Collect(); System.GC....

    详解C#中的定时器Timer类及其垃圾回收机制

    它不适用于控制台应用程序,因为控制台没有消息循环。 2. **System.Threading.Timer**:这是一个基于.NET ThreadPool的多线程定时器,它提供了更精确的计时,并且可以在任何类型的应用程序中使用,包括控制台程序。...

    Java的垃圾收集器(GC)整理.pdf

    - **System.gc()**:虽然调用此方法会触发垃圾收集,但并不保证一定执行,且可能导致性能下降,因此不推荐在生产环境中频繁使用。 - **JVM参数调整**:通过设置JVM启动参数,可以控制垃圾收集器的行为,如内存大小...

    JAVA中销毁一个对象的方法.doc

    - **紧急情况**:当程序遇到内存不足的情况时,可以尝试调用`System.gc()`来尝试释放一些内存。 - **测试目的**:在开发阶段,为了模拟特定的运行环境,可能会手动触发垃圾回收以观察程序的行为。 **3.3 注意事项**...

Global site tag (gtag.js) - Google Analytics