嘿我用这段代码测试Runtime.freeMemory():
Runtime runtime = Runtime.getRuntime();
long freeMemory = runtime.freeMemory();
// This is some arbitary factor that should work <= 1
double factor = 0.8;
int size = (int) (factor * freeMemory);
byte[] testArray = new byte[size];
我正在创建一个大小接近freeMemory值的字节数组。出于某种原因,特别是当我将程序的内存限制在大约8MB时,代码会抛出任何因子的OutOfMemory异常&gt; 0.55。这真的没有意义,当然freeMemory意味着freeMemory,我希望它有点出来,但不是实际上是免费的双倍。
有关最新进展的任何建议吗? 感谢
(请注意,在我的测试中,我将程序可用的内存限制为8MB或16MB,使用-Xmx8M等。)
答案 0 :(得分:2)
实际上,你的自由记忆分为两代:http://java.sun.com/docs/hotspot/gc1.4.2/一个是“年轻”一代,一个是“终身”一代。 如果您使用-verbose:gc -XX:+ PrintGCDetails VM设置运行,您可以看到每代生成的数量。我发现我可以完全填满我的一代,但不会超过这个。
答案 1 :(得分:0)
在使用runtime.gc()
创建测试数组之前尝试进行垃圾回收。
如果你没有创建一个全新的JVM,那么每次你都可以通过不同的开始状态来获得它。
我的工作价值观&gt; 1. 1.25例如。然后我得到一个'堆空间'异常。
在这里,也许你想要'maxMemory()'。
public class Mem2 {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
runtime.gc();
long freeMemory = runtime.freeMemory();
// This is some arbitary factor that should work <= 1
double factor = 1.29;
int size = (int) (factor * freeMemory);
System.out.println(" freememory is " + freeMemory);
System.out.println(" size is " + size);
System.out.println("the total memory is " + runtime.totalMemory());
System.out.println(" the max memory is " + runtime.maxMemory());
byte[] testArray = new byte[size];
}
}
输出:
freememory is 84466864
size is 108962254
the total memory is 85000192
the max memory is 129957888
Process finished with exit code 0
所以似乎有大约20M我无法解释。
我认为totalMemory()是当前由JVM分配的内存量,freeMemory()是使用了多少内存,而maxMemory()是硬限制。
您可以在代码中看到totalMemory()
和freememory()
之间的相互作用。
public class Mem3 {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
for (int i = 0; true; i++) {
runtime.gc();
int size = i * 10000000;
System.out.println(" i is " + i);
System.out.println(" size is " + size);
System.out.println("b freememory is " + runtime.freeMemory());
System.out.println("b the total memory is " + runtime.totalMemory());
System.out.println("b the max memory is " + runtime.maxMemory());
byte[] testArray = new byte[size];
System.out.println(" array " + testArray.length);
System.out.println("a freememory is " + runtime.freeMemory());
System.out.println("a the total memory is " + runtime.totalMemory());
System.out.println("a the max memory is " + runtime.maxMemory());
System.out.println(" ");
}
}
}
如果你运行它并查看前后值,你可以看到发生了什么。注意在6和7之间发生的事情:
i is 6
size is 60000000
b freememory is 84300496
b the total memory is 85000192
b the max memory is 129957888
array 60000000
a freememory is 24300472
a the total memory is 85000192
a the max memory is 129957888
i is 7
size is 70000000
b freememory is 84300496
b the total memory is 85000192
b the max memory is 129957888
array 70000000
a freememory is 59258168
a the total memory is 129957888
a the max memory is 129957888
我们在6中看到,在分配60M之后,剩下大约24M。然而,在7,我们已经超过了一个门槛。已分配更多内存(注意totalMemory),freeMemory现在不到60M。
答案 2 :(得分:0)
掌握此问题的最佳方法是通过分析器运行代码,该分析器能够向您显示系统内存随时间的分配情况。如果您正在使用Eclipse,请确保已安装TPTP,我确信其他大型IDE在某处具有相同的功能。
答案 3 :(得分:0)
我认为这与堆分区的大小有关。当JVM启动时,它会将可用堆内存分成多个“空格”;例如新创建的对象有一个空间,tenured对象的空间,在第一个GC循环中存活的对象的“eden”空间,依此类推。空间的实际大小是可调的(通过JVM选项),但“新对象”空间可能远小于8Mb。
当您尝试分配包含55%报告的可用内存的数组时,内存管理器需要在“新对象”空间中找到该数量的连续内存。如果您正在获取OOME,那是因为实际的分区使得所需的连续内存量不可用......即使在GC运行之后也是如此。
基本上,您尝试使用太小的堆来运行JVM,以实现您的目标。作为一般原则,与Java的堆大小吝啬是一个坏主意。如果你给它足够的内存,你的应用程序将运行得更快(并且问题更少)。
答案 4 :(得分:0)
这个答案是基于spong在主要问题上的评论。
如果不是尝试在一个chuck中创建数组,而是将其创建分成许多较小的数组,则可以将空闲内存填充到0.98左右。
Runtime runtime = Runtime.getRuntime();
long freeMemory = runtime.freeMemory();
// This is some arbitary factor that should work <= 1
double factor = 0.8;
int size = (int) (factor * freeMemory);
int slice = 100;
byte[][] testArrays = new byte[slice][1];
for (int i = 1; i <= slice; i++) {
testArrays[i-1] = new byte[size / slice];
System.out.println("Allocated: " + i * size / slice);
}
System.out.println("Created! "+testArrays.length);