当前位置:  开发笔记 > 编程语言 > 正文

如何在Java中释放内存?

如何解决《如何在Java中释放内存?》经验,为你挑选了6个好方法。

有没有办法在Java中释放内存,类似于C的free()功能?或者将对象设置为null并依赖GC是唯一的选择?



1> Daniel Pryde..:

Java使用托管内存,因此分配内存的唯一方法是使用new运算符,并且释放内存的唯一方法是依靠垃圾收集器.

此内存管理白皮书(PDF)可能有助于解释正在发生的事情.

您也可以打电话System.gc()建议垃圾收集器立即运行.但是,Java Runtime做出最终决定,而不是代码.

根据Java文档,

调用gc方法表明Java虚拟机花费了大量精力来回收未使用的对象,以使其当前占用的内存可用于快速重用.当控制从方法调用返回时,Java虚拟机已尽最大努力从所有丢弃的对象中回收空间.


没有Pablo,它不会强制GC运行.
它确实强制垃圾收集器运行.虽然它不会强迫它释放内存......

2> Adamski..:

似乎没有人提到明确设置对象引用null,这是一种"释放"你可能想要考虑的内存的合法技术.

例如,假设您List在方法的开头声明了一个大小变得非常大的方法,但只是在方法的中途才需要.您可以在此时将List引用设置null为允许垃圾收集器在方法完成之前潜在地回收此对象(并且引用无论如何都会超出范围).

请注意,我很少在现实中使用此技术,但在处理非常大的数据结构时,值得考虑.


如果你真的在一个对象上做了很多工作,这个对象只用于我建议的方法的一部分; 你的方法过于复杂,将方法分解为前后部分,或者对前半部分代码使用一个块(后者对于测试脚本更有用)
将对象引用设置为null很重要的地方是从另一个长期存在的对象(或者可能来自静态var)引用它.例如,如果您有一个长期存在的大型对象数组,并且停止使用其中一个对象,则应将数组引用设置为null以使该对象可用于GC.

3> Dean J..:
System.gc(); 

运行垃圾收集器.

调用gc方法表明 Java虚拟机花费了大量精力来回收未使用的对象,以使其当前占用的内存可用于快速重用.当控制从方法调用返回时,Java虚拟机已尽最大努力从所有丢弃的对象中回收空间.

不建议.

编辑:我在2009年写了原始回复.现在是2015年.

垃圾收集器在Java已经存在的约20年里变得越来越好.此时,如果您手动调用垃圾收集器,您可能需要考虑其他方法:

如果你在有限数量的机器上强制使用GC,那么可能值得让负载均衡器远离当前机器,等待它完成为连接的客户端服务,在一段时间后暂停连接超时,然后再努力-restart JVM.这是一个糟糕的解决方案,但如果您正在查看System.gc(),强制重启可能是一个可能的权宜之计.

考虑使用不同的垃圾收集器.例如,(过去六年中的新)G1收集器是一个低暂停模型; 它总体上使用了更多的CPU,但是最好永远不要强制执行硬件.由于服务器CPU现在几乎都拥有多个内核,因此这是一个非常好的权衡.

看看调整内存使用的标志.特别是在较新版本的Java中,如果没有那么多长期运行的对象,请考虑增加堆中newgen的大小.newgen(年轻)是分配新对象的地方.对于Web服务器,为请求创建的所有内容都放在此处,如果此空间太小,Java将花费额外的时间将对象升级到更长寿的内存,在这些内存中它们的销售成本更高.(如果newgen稍微太小,你就要付钱了.)例如,在G1中:

XX:G1NewSizePercent(默认为5;可能无关紧要.)

XX:G1MaxNewSizePercent(默认为60;可能会提高此值.)

考虑告诉垃圾收集器你没有时间更长的停顿.这将导致更频繁的GC运行,以允许系统保持其余的约束.在G1:

XX:MaxGCPauseMillis(默认为200.)


@Jesper,Dean的回答说"建议".事实上,他发布了方法的javadocs中的确切文档......
@Software Monkey:是的,我本来可以编辑它.但是,由于Dean J显然很活跃(仅在几分钟之前发布),我认为要求他这样做是礼貌的.如果他没有,我会回到这里进行编辑并删除我的评论.

4> Dakkaron..:

*"我个人依赖于将变量归零作为占位符以便将来正确删除.例如,在实际删除(使null)数组本身之前,我花时间取消数组的所有元素."

这是不必要的.Java GC的工作方式是找到没有引用它们的对象,所以如果我有一个带有引用(=变量)的Object x指向它,GC就不会删除它,因为有一个引用到那个对象:

a -> x

如果你为null,则发生这种情况:

a -> null
     x

所以现在x没有指向它的引用,将被删除.当您设置引用与x不同的对象时,会发生同样的事情.

因此,如果您有一个引用对象x,y和z的数组arr以及一个引用该数组的变量a,它看起来像这样:

a -> arr -> x
         -> y
         -> z

如果你为null,则发生这种情况:

a -> null
     arr -> x
         -> y
         -> z

所以GC发现arr没有设置引用并删除它,这给你这个结构:

a -> null
     x
     y
     z

现在GC找到x,y和z并删除它们.取消数组中的每个引用都不会有任何改进,它只会消耗代码中的CPU时间和空间(也就是说,它不会比这更糟糕.GC仍然能够执行它应该的方式).



5> 小智..:

想要从任何程序(java或不是java)释放内存的正当理由是在操作系统级别为其他程序提供更多内存.如果我的java应用程序使用250MB,我可能希望将其强制降至1MB,并将249MB提供给其他应用程序.


但是,释放Java堆中的存储空间(通常情况下)不会使存储可供其他应用程序使用.

6> nsandersen..:

为了扩展Yiannis Xanthopoulos和Hot Licks的回答和评论(对不起,我还不能发表评论!),您可以像下面的示例一样设置VM选项:

-XX:+UseG1GC -XX:MinHeapFreeRatio=15 -XX:MaxHeapFreeRatio=30

在我的jdk 7中,如果在VM空闲后GC后超过30%的堆可用,则它将释放未使用的VM内存。您可能需要调整这些参数。

虽然我没有在下面的链接中强调它,但是请注意,如果您碰巧具有多个内核,则某些垃圾收集器可能不会遵循这些参数,并且默认情况下,java可能会为您选择其中一个参数(因此,上面的UseG1GC参数)。

VM参数

更新:对于Java 1.8.0_73,我已经看到JVM偶尔会使用默认设置释放少量内容。似乎只在大约70%的堆未使用时才这样做。.不知道如果操作系统的物理内存不足,是否会更积极地释放。

推荐阅读
臭小子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有