joc*_*ull 25 java garbage-collection memory-leaks memory-management
我试图在Java中处理正确的内存使用和垃圾收集.无论如何我都不是新手程序员,但在我看来,一旦Java接触到某些内存,它就永远不会被其他应用程序使用.在这种情况下,您必须确保峰值内存永远不会太高,或者您的应用程序将持续使用峰值内存使用量.
我写了一个小样本程序试图证明这一点.它基本上有4个按钮......
BigList = new ArrayList<string>()
使用大约25,000,000个长字符串项填充类范围变量.BigList.clear()
BigList = new ArrayList<string>()
分配列表 - 再次(缩小列表大小)System.gc()
- 是的,我知道这并不意味着GC会真正运行,但这就是我们所拥有的.接下来,我在Windows,Linux和Mac OS上进行了一些测试,同时使用默认任务监视器来检查进程报告的内存使用情况.这是我发现的......
new
几次重新分配列表然后多次调用GC将减少内存使用量回到起始级别.IMO,这是可以接受的.任何人都可以向我解释这个吗?有些人告诉我一些关于"堆"记忆的东西,但我仍然不完全理解它,我不确定它是否适用于此.据我所知,我不应该看到我在Windows和Linux上的行为.
这只是Mac OS的活动监视器测量内存使用情况的方式还是有其他不同之处?我宁愿不让我的程序闲置大量的RAM使用.感谢您的见解.
Wil*_*ung 19
Sun/Oracle JVM不会将不需要的内存返回给系统.如果给它一个较大的最大堆大小,并且实际上在某个时候使用了该堆空间,则JVM不会将其返回给OS以供其他用途.其他JVM会这样做(JRockit曾经,但我不认为它会再做).
因此,对于Oracles JVM,您需要调整应用程序和系统的峰值使用率,这就是它的工作原理.如果您正在使用的内存可以使用字节数组进行管理(例如使用图像或其他内容),那么您可以使用映射的字节缓冲区而不是Java字节数组.映射的字节缓冲区直接从系统中获取,而不是堆的一部分.当你释放这些对象时(并且它们是GC,我相信,但不确定),内存将返回到系统.假设它甚至可以应用,你可能不得不玩那个.
...但在我看来,一旦Java触及一些记忆,它就永远消失了.你永远不会得到它.
这取决于你的意思是"永远消失".
我还听说过有人说,某些JVM 也给内存给操作系统时,他们都愿意并能够.遗憾的是,考虑到低级内存API通常的工作方式,JVM必须返回整个段,并且"撤出"一个段以便可以返回它往往很复杂.
但我不会依赖它...因为有各种各样的东西可以阻止记忆被回馈.可能是JVM 不会将内存返回给操作系统.但在JVM将继续使用它的意义上,它并没有"永远消失".即使JVM再也没有接近峰值使用,所有内存都将有助于提高垃圾收集器的运行效率.
在这种情况下,您必须确保峰值内存永远不会太高,否则您的应用程序将不断耗尽数百MB的RAM.
事实并非如此.假设您采用的是从小堆开始并让它增长的策略,JVM不会要求比峰值内存大得多的内存.JVM不会持续占用更多内存......除非你的应用程序有内存泄漏并且(因此)其峰值内存要求没有限制.
(OP的评论表明,这不是他想说的.即便如此,这也是他所说的.)
关于垃圾收集效率的主题,我们可以将高效垃圾收集器的运行成本建模为:
cost ~= (amount_of_live_data * W1) + (amount_of_garbage * W2)
Run Code Online (Sandbox Code Playgroud)
其中W1和W2是(我们假设)取决于收集器的常数.(实际上,这是一个过度简化.第一部分不是活动对象数量的线性函数.但是,我声称它对以下内容无关紧要.)
然后收集器的效率可以表示为:
efficiency = cost / amount_of_garbage_collected
Run Code Online (Sandbox Code Playgroud)
哪个(如果我们假设GC收集所有数据)扩展为
efficiency ~= (amount_of_live_data * W1) / amount_of_garbage + W2.
Run Code Online (Sandbox Code Playgroud)
当GC运行时
heap_size ~= amount_of_live_data + amount_of_garbage
Run Code Online (Sandbox Code Playgroud)
所以
efficiency ~= W1 * (amount_of_live_data / (heap_size - amount_of_live_data) )
+ W2.
Run Code Online (Sandbox Code Playgroud)
换一种说法:
另一点是,对于高效的复制收集器,W2仅涵盖了"从空间"中清空垃圾对象所占空间的成本.其余的(跟踪,将活动对象复制到'空间',以及将它们占用的'从空间'归零)是初始方程的第一项的一部分;即由W1覆盖.这意味着W2很可能比W1小得多......并且最终方程的第一项有效期更长.
现在显然这是一个理论分析,成本模型简化了真正的垃圾收集器的真正工作方式.(并没有考虑到应用程序正在进行的"真正"工作,或者是系统级别的关闭太多内存的影响.)然而,数学告诉我,从GC效率的角度来看,这是一个很大的问题.堆确实帮了很多忙.
归档时间: |
|
查看次数: |
3242 次 |
最近记录: |