Runtime - why does freeMemory () not show the correct memory?

Below is a snippet of code for learning about 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 way out is

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

Why does freeMemory not reflect the memory consumed by two objects?


To be more clear, the question arises that the call to getMemory () does not display the expected result, even if two objects are created and are not related to the GC. Two GC calls are made to try to make sure that the getMemory () call numbers are correct .. and BTW, there is no GC call after creating objects .. so pls note that I am not trying to create a GC after creating objects ..

+4
source share
4 answers

Memory management in JVM HotSpot:

Another desirable garbage collector feature is fragmentation restriction. When memory for garbage objects is freed up, free space may appear in small pieces in various areas, there will not be enough space in any adjacent area that will be used to allocate a large object. The approach to removing fragmentation is called compaction, discussed among the various garbage collector designs below.

Memory management in JVM HotSpot (PDF format).

This behavior can be highly dependent on the particular implementation of the garbage collection. For instance:

Parallel Mark Compact

  • Stop world
  • The heap is divided into pieces of a fixed size (> 2kb now, most likely, will increase or will be subject to ergonomics)
  • Chunk is a unit of summing live data.
  • Parallel label
  • Record live data addresses in an external bitmap
  • Find current real-time data size
  • Find tight pieces, i.e. those that are (almost) full of living objects

I made this sample (with abusive String concatenation to use 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. } } 

Exit

Free memory (before GC): 3751800

Free memory (after GC): 5036104

Free memory (after creating the line): 5012048


If I use a relatively small number of iterations in a loop (say 10), the extra space does not appear in freeMemory() , and I would get something like the following:

Free memory (before GC): 3751800

Free memory (after GC): 5036040

Free memory (after creating the line): 5036040

+3
source

Good question, since you expect the INCREASED memory usage to be reflected, this seems like a logical test. You can assume that this behavior is due to the fact that the heap management system and the garbage collector are somewhat more complicated than a simple free vs selected border. The allocation is probably done in chunks much larger than your String + one Integer string, and therefore free memory is likely to be counted by summing the free fragments.

+1
source

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

0
source

Try to allocate more memory and you will see an increase. I assume java predetermines at least enough bytes (how smarter!) To hold your lines, or they were already in the string pool.

0
source

All Articles