Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用getRuntime().freeMemory()产生意外结果_Java_Memory_Jvm - Fatal编程技术网

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的唯一逻辑解释。垃圾收集可以在任何时间点进行。此外,在代码开始执行时,可能已经存在任意数量的可回收垃圾。因此,这种差异是任意的,毫无意义。这个数字甚至可以是负数,例如,当先前存在的垃圾占用的内存超过代码中分配的对象时。