Java 使用getRuntime().freeMemory()产生意外结果
我计划使用Java 使用getRuntime().freeMemory()产生意外结果,java,memory,jvm,Java,Memory,Jvm,我计划使用getRuntime().freemory()粗略估计一个java方法消耗了多少内存。我试图通过以下方式实现这一目标: long beforeUsedMem=Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory(); foo(); long afterUsedMem=Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory(); l
getRuntime().freemory()
粗略估计一个java方法消耗了多少内存。我试图通过以下方式实现这一目标:
long beforeUsedMem=Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory();
foo();
long afterUsedMem=Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory();
long actualMemUsed=afterUsedMem-beforeUsedMem;
为了测试这是否真的可以工作,我运行了下面的代码
long beforeUsedMem=Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory();
List<Integer> list = new ArrayList<>();
for(int i = 0 ;i<1000;i++)
list.add(i);
long afterUsedMem=Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory();
long actualMemUsed=afterUsedMem-beforeUsedMem;
System.out.println("mem used "+actualMemUsed);
但是,如果我从0->100000循环,输出结果是
mem used 0
mem used 2684368
有人能解释一下jvm为什么会这样工作吗?问题是
getRuntime().freemory()
没有做你认为它在做的事情
JVM将根据需要分块分配内存,并且根据您使用的GC,还可能将内存返回给操作系统。因此,从内存选项中看到的结果取决于JVM正在做什么,而不是单个方法做什么
如果您想测量Java方法分配的对象数量,那么应该查看JMH,特别是GC分析器。这将重复运行您的方法,然后根据通过JMX运行的垃圾收集收集的信息进行平均
我写了一篇关于StringBuilder性能的文章,其中使用了JMH和prof gc。该文件位于GitHub以供参考
TL;DR是指您想要的是:
@State(Scope.Benchmark)
public class StringBuilderBenchmark {
@Benchmark
public String testEmptyBuffer() {
StringBuffer buffer = new StringBuffer();
return buffer.toString();
}
}
然后使用mvn JMH arhectype使用JMH编译/构建此文件,并使用prof gc运行它:
java -jar target/benchmarks.jar \
-wi 5 -tu ns -f 1 -bm avgt -prof gc
然后,它将重复运行该方法,并给出每次方法调用分配的平均字节数
注意,它不会测量所需的一次性初始化;例如,如果您懒洋洋地分配一个包含一百万个条目的巨型地图,则此过程不会计算它的数量
有关JMH的更多信息可用。总计和免费相等,因此结果为0。然后使用一些内存,使值不再为0?@missing分号为什么在我添加到列表后,可用内存会相同?总内存=10.000.000,使用内存后的可用内存=10.000.000:总内存=10.000.000,可用内存=8.000.000。不能说我也不期望它是0,但这是我能想到的sry的唯一逻辑解释。垃圾收集可以在任何时间点进行。此外,在代码开始执行时,可能已经存在任意数量的可回收垃圾。因此,这种差异是任意的,毫无意义。这个数字甚至可以是负数,例如,当先前存在的垃圾占用的内存超过代码中分配的对象时。