运行时 - 为什么 freeMemory() 没有正确显示消耗的内存?

发布于 2024-09-13 00:12:47 字数 1171 浏览 3 评论 0原文

下面是检查内存的代码片段

public class TestFreeMemory {

    public static void main(String ... args){

        Runtime rt = Runtime.getRuntime();
        System.out.println("Free Memory (Before GC): " + rt.freeMemory());

        rt.gc();
        System.out.println("Free Memory (After GC1): " + rt.freeMemory());

        rt.gc(); // Second time to ensure results are consistent 
                 // MAY BE has collected all non-reachable objects
        System.out.println("Free Memory (After GC2): " + rt.freeMemory());

        String s = new String("abcd");
        Integer i = new Integer(12345);
        System.out.println("Free Memory (After String Creation): " + rt.freeMemory());
        // Why is freeMemory not reflecting the memory consumed by two objects
    }

}

,输出为

Free Memory (Before GC): 1859672
Free Memory (After GC1): 1911768
Free Memory (After GC2): 1911768
Free Memory (After String Creation): 1911768

Why is freeMemory not反映两个对象消耗的内存?


更清楚地说,问题是 getMemory() 调用没有显示预期结果,即使创建了两个对象并且与 GC 无关。进行两次 GC 调用只是为了确保 getMemory() 调用的数量正确。顺便说一句,创建对象后没有 GC 调用。所以请注意,创建对象后我没有尝试进行 GC ..

Below is the code snippet to examine the memory

public class TestFreeMemory {

    public static void main(String ... args){

        Runtime rt = Runtime.getRuntime();
        System.out.println("Free Memory (Before GC): " + rt.freeMemory());

        rt.gc();
        System.out.println("Free Memory (After GC1): " + rt.freeMemory());

        rt.gc(); // Second time to ensure results are consistent 
                 // MAY BE has collected all non-reachable objects
        System.out.println("Free Memory (After GC2): " + rt.freeMemory());

        String s = new String("abcd");
        Integer i = new Integer(12345);
        System.out.println("Free Memory (After String Creation): " + rt.freeMemory());
        // Why is freeMemory not reflecting the memory consumed by two objects
    }

}

and the output is

Free Memory (Before GC): 1859672
Free Memory (After GC1): 1911768
Free Memory (After GC2): 1911768
Free Memory (After String Creation): 1911768

Why is freeMemory not reflecting the memory consumed by two objects ?


To be more clear, the question is about getMemory() call not showing up expected result even though two objects are created and not related to GC. Two GC calls are made just to try to make sure the numbers of getMemory() call are correct.. and BTW, there's no GC call after objects are created.. so pls Note that i am not trying for a GC after objects are created ..

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

沉睡月亮 2024-09-20 00:12:47

HotSpot JVM 上的内存管理:

另一个理想的垃圾收集器
特征是限制
碎片化。 当内存为
垃圾对象被释放,释放
空间可能会以小块的形式出现
各个领域,以便可能
任何一处都没有足够的空间
用于的连续区域
分配一个大对象。

消除碎片化的方法
称为压缩,在
各种垃圾收集器设计
下面的选择。

HotSpot JVM 中的内存管理(PDF 格式)。

此行为可能非常依赖于垃圾收集的特定实现。例如:

平行标记紧凑型

  • 停止世界
  • 堆分为固定大小的块(现在> 2kb,可能会增加或减少)
    符合人体工程学)
  • Chunk是实时数据汇总的单位
  • 平行标记
  • 在外部位图中记录实时数据地址
  • 查找每个块的实时数据大小
  • 找到密集的块,即(几乎)充满活动对象的块

我制作的 实时对象的块此示例(滥用字符串连接以占用更多内存):

public class TestFreeMemory {

 static void allocateSomeMemory(){
  long[][] array = new long[400][400];
 }

    public static void main(String ... args){

        Runtime rt = Runtime.getRuntime();

        allocateSomeMemory(); // once we leave, our array is not reachable anymore 
        System.out.println("Free Memory (Before GC): " + rt.freeMemory());     
        rt.gc();
        System.out.println("Free Memory (After GC): " + rt.freeMemory());

        String a = new String("A");
        for(int i = 0; i < 100; i++){
         a+="B";
        }

        System.out.println("Free Memory (After String Creation): " + rt.freeMemory());
        // Less free memory expected.
    }

}

输出

可用内存(GC 之前):3751800

可用内存(GC 后):5036104

释放内存(创建字符串后):
5012048


如果我在循环中使用相对较少的迭代次数(例如 10),则额外的空间不会出现在 freeMemory() 中,并且我会得到如下内容:

可用内存(GC 之前):3751800

可用内存(GC后):5036040

释放内存(创建字符串后):
5036040

Memory Management on HotSpot JVM:

Another desirable garbage collector
characteristic is the limitation of
fragmentation. When the memory for
garbage objects is freed, the free
space may appear in small chunks in
various areas such that there might
not be enough space in any one
contiguous area to be used for
allocation of a large object.
One
approach to eliminating fragmentation
is called compaction, discussed among
the various garbage collector design
choices below.

Memory Management in HotSpot JVM (PDF Format).

This behavior can be very dependent on the particular implementation of the garbage collection. For example:

Parallel Mark Compact

  • Stop-the-world
  • Heap divided into fixed-size chunks (> 2kb now, will likely increase or be
    subject to ergonomics)
  • Chunk is unit of live data summarization
  • Parallel mark
  • Record live data addresses in external bitmap
  • Find per chunk live data size
  • Find dense chunks, i.e., ones that are (almost) full of live objects

I've made this sample (with abusive String concatenation to use up more memory):

public class TestFreeMemory {

 static void allocateSomeMemory(){
  long[][] array = new long[400][400];
 }

    public static void main(String ... args){

        Runtime rt = Runtime.getRuntime();

        allocateSomeMemory(); // once we leave, our array is not reachable anymore 
        System.out.println("Free Memory (Before GC): " + rt.freeMemory());     
        rt.gc();
        System.out.println("Free Memory (After GC): " + rt.freeMemory());

        String a = new String("A");
        for(int i = 0; i < 100; i++){
         a+="B";
        }

        System.out.println("Free Memory (After String Creation): " + rt.freeMemory());
        // Less free memory expected.
    }

}

Output:

Free Memory (Before GC): 3751800

Free Memory (After GC): 5036104

Free Memory (After String Creation):
5012048


If I use a relatively small number of iterations in the loop (say 10), the extra space does not show up in freeMemory(), and I'd get something like this:

Free Memory (Before GC): 3751800

Free Memory (After GC): 5036040

Free Memory (After String Creation):
5036040

在风中等你 2024-09-20 00:12:47

这是一个很好的问题,因为您期望内存使用量的增加得到反映,这似乎是一个逻辑测试。您可以假设此行为是因为堆管理和垃圾收集系统比简单的“空闲”与“分配”边界更复杂。分配可能是以比一个字符串 + 一个整数大得多的块来完成的,因此可用内存可能是通过对可用块求和来计算的。

It's a good question since you are expecting an INCREASE in memory usage to be reflected it seems a logical test. You can assume this behaviour is because the Heap management and garbage collection system is somewhat more complex that a simple Free vs Allocated boundary. Allocation is probably done in chunks much bigger than your one String + one Integer and so free memory is likely to be counted by summing up free chunks.

凶凌 2024-09-20 00:12:47

GC 不会在您调用它时释放内存,而是在需要更多内存时释放内存。

The GC does not free memory when you call it, but when more memory is needed.

三生池水覆流年 2024-09-20 00:12:47

尝试分配更多内存,您会看到增加。我猜java至少预先分配了足够的字节(多聪明啊!)来保存你的字符串或者它们已经在字符串池中了。

Try to allocate more memory and you will see an increase. I guess java preallocates at least enough bytes (how smart!) to hold your strings OR they were in the string pool already.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文