Reputation: 2011
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
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
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
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