Problem with Runtime.freeMemory() - Java


Hey I'm testing out Runtime.freeMemory() with this code:

 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];

I'm creating a byte array of size close to the freeMemory value. For some reason, especially when I limit the memory of the program to around 8MB, the code throws an OutOfMemory exception for any factor > 0.55. This really doesnt make sense, surely freeMemory means freeMemory, I expect it to be a little out, but not double what actually is free.

Any suggestions on whats going on? Thanks

(Note in my tests im limiting the memory available to the program to 8MB or 16MB, using -Xmx8M etc.)


Try garbage collecting before creating the test array with runtime.gc().

If you aren't creating a brand new JVM each time you could be getting bit by having different start states.

Mine works for values > 1. 1.25 for example. Then I get a 'heap space' exception.

Here, perhaps you want 'maxMemory()' instead.

public class Mem2 {
    public static void main(String[] args) {

        Runtime runtime = Runtime.getRuntime();

        long freeMemory = runtime.freeMemory();

        // This is some arbitary factor that should work 

The best way of getting a grip on this would be to run your code through a profiler that is capable of showing you how the memory in your system is being allocated over time. If you're using Eclipse make sure you've got TPTP installed, I'm sure the other big IDEs have the same feature somewhere.

I think that this is to do with the sizes of the heap's partitions. When the JVM starts, it is going to split the available heap memory into a number of "spaces"; e.g. there is a space for newly created objects, a space for tenured objects, an "eden" space for objects that survive the first GC cycle, and so on. The actual sizes of the spaces are tunable (via JVM options), but the chances are that the "new objects" space is considerably less than 8Mb.

When you then try to allocate your array containing 55% of the reported free memory, the memory manager needs to find that amount of contiguous memory in the "new objects" space. If you are getting an OOME, that is because the actual partitioning is such that the required amount of contiguous memory is not available ... even after the GC has run.

Basically, you are trying to run the JVM with too small a heap for what you are trying to do. As a general principle, it is a bad idea to be miserly with Java's heap size. Your application will run faster (and with less problems) if you give it plenty of memory.

By : Stephen C

This video can help you solving your question :)
By: admin