marcorossi
marcorossi

Reputation: 2011

Java: on the cost of calling Runtime.freeMemory(), Runtime.totalMemory() and Runtime.maxMemory()

I have a Map in memory that stores my objects. I'd like to flush to memory when I'm running out of memory. I'm doing this right now:

void add(K key, V value) {
    if (underPressure()) {
        flush(innerMap);
    }
    innerMap.add(k, v);
}

boolean underPressure() {
    Runtime rt = Runtime.getRuntime();
    long maxMemory = rt.maxMemory();
    long freeMemory = rt.freeMemory();

    return (double) freeMemory / maxMemory < threshold;
}

As underPressure() is called at each insert, how expensive is it? To my understanding, as it's an approximation, it should be somehow cached by the jvm, but does anybody know more about this for real?

Upvotes: 9

Views: 2553

Answers (3)

cruftex
cruftex

Reputation: 5723

Since Java 7 there is no need to poll the free memory any more. It is possible to register for a garbage collection event. See this post: http://www.fasterj.com/articles/gcnotifs.shtml

So the best way I can think of, is to check the free memory after the garbage collection and then free additional space, if needed.

Upvotes: 5

Jayan
Jayan

Reputation: 18459

Why not use JMXBeans to do this. It was designed to simplify this kind of operations..

From the docs...

The API provides access to information such as:

Number of classes loaded and threads running
Virtual machine uptime, system properties, and JVM input arguments
Thread state, thread contention statistics, and stack trace of live threads
Memory consumption
Garbage collection statistics
Low memory detection
On-demand deadlock detection
Operating system information

Specifically see the example code in MemoryPoolMXBean

Upvotes: 3

pgras
pgras

Reputation: 12770

Not directly answering your question but as already said in the comments freeMemory counts the free memory rather than the memory that would be available after a GC, thus if you call freeMemory just before the GC runs you may think you are reaching your "underPressure" limit but you could as well have plenty of free memory after the next GC run.

Another approach may be to create a softly reachable object and to check if it was claimed by the GC:

something like:

SoftReference<Object> sr = new SoftReference<Object>(new Object(),new ReferenceQueue<Object>());
public boolean underPressure(){
    if (sr.isEnqueued()) {
        // recreate object to monitor
        sr = new SoftReference<Object>(new Object(),new ReferenceQueue<Object>());
        return true;
    }
    return false;
}

Upvotes: 2

Related Questions