Ere*_*evi 4 java out-of-memory
我有一个导致OutOfMemoryError的应用程序,所以我尝试使用Runtime.getRuntime().freeMemory()调试它.这是我得到的:
freeMemory=48792216
## Reading real sentences file...map size=4709. freeMemory=57056656
## Reading full sentences file...map size=28360. freeMemory=42028760
freeMemory=42028760
## Reading suffix array files of main corpus ...array size=513762 freeMemory=90063112
## Reading reverse suffix array files... array size=513762. freeMemory=64449240
Run Code Online (Sandbox Code Playgroud)
我试着理解freeMemory的行为.它从48 MB开始,然后 - 在我读取一个大文件后 - 它跳到最大57 MB,然后再次向下跳到42 MB,然后 - 在我读取一个非常大的文件(513762个元素)之后它跳到90 MB,然后再次下降到64 MB.
这里发生了什么?我怎样才能理解这些数字?
java内存有点棘手.你的程序在jvm里面运行,jvm在os里面运行,os使用你的计算机资源.当你的程序需要内存时,jvm会看到它是否已经向os请求了一些当前未使用的内存,如果没有足够的内存,jvm将询问操作系统,如果可能的话,获取一些内存.
jvm会不时地查看不再使用的内存,并将释放它.根据(大量)因素,jvm还可以将该内存返回给操作系统,以便其他程序可以使用它.
这意味着,在任何给定时刻,你都有jvm从os获得的一定数量的内存,以及jvm当前使用的一定数量的内存.
在任何给定的点上,jvm可能会拒绝获取更多内存,因为它已经被这样做了,或者os可能会拒绝jvm访问更多内存,要么是因为再次指示这样做,要么仅仅是因为没有更多免费的公羊.
当您在计算机上运行程序时,您可能没有对jvm进行任何限制,因此您可以使用大量的ram.在谷歌应用程序上运行时,谷歌运营商可能会对jvm施加一些限制,因此可用的内存可能更少.
Runtime.freeMemory会告诉你jvm从os获得的ram目前有多少是免费的.
当你分配一个大对象,比如一个MB时,jvm可能需要更多ram到os,比如5 MB,导致freeMemory比以前多4 MB,这是违反直觉的.分配另一个MB可能会按预期缩小可用内存,但后来jvm可能会决定向thenos释放一些内存,而freeMemory将再次缩小,没有明显的原因.
将totalMemory和maxMemory与freeMemory结合使用,您可以更好地了解当前的ram限制和消耗.
要了解为什么消耗的ram超出预期,您应该使用内存分析器.一个简单但有效的包装与visualvm,一个通常已经与jdk一起安装的工具.在那里你将能够看到程序中使用ram的原因以及为什么jvm无法回收内存.
(注意,jvm的内存系统比这复杂得多,但我希望这种简化可以帮助你理解一个完整而复杂的图片)