package org.kevoree.library.android.osmdroid; /** * Created by jed * User: jedartois@gmail.com * Date: 16/04/12 * Time: 09:14 */ public class LowMemory { /** * Free memory seen when caller indicated an out of * memory situation. Becomes a low memory watermark * for five seconds that causes isLowMemory to return * true if free memory is lower than this value. * This allows the JVM a chance to recover memory * rather than start new operations that are probably * doomed to failure due to the low memory. * */ private long lowMemory; /** * Time in ms corresponding to System.currentTimeMillis() when * lowMemory was set. */ private long whenLowMemorySet; /** * Set a low memory watermark where the owner of this object just hit an * OutOfMemoryError. The caller is assumed it has just freed up any * references it obtained during the operation, so that the freeMemory call * as best as it can reflects the memory before the action that caused the * OutOfMemoryError, not part way through the action. * */ public void setLowMemory() { // Can read lowMemory unsynchronized, worst // case is that we force extra garbage collection. if (lowMemory == 0L) { // The caller tried to dereference any objects it // created during its instantation. Try to garbage // collect these so that we can a best-guess effort // at the free memory before the overall operation we are // failing on occurred. Of course in active multi-threading // systems we run the risk that some other thread just freed // up some memory that throws off our calcuation. This is // avoided by clearing lowMemory some time later on an // isLowMemory() call. boolean interrupted = false; for (int i = 0; i < 5; i++) { System.gc(); System.runFinalization(); try { Thread.sleep(50L); } catch (InterruptedException e) { interrupted = true; } } if (interrupted) { // reinstate flag Thread.currentThread().interrupt(); } } synchronized (this) { if (lowMemory == 0L) { lowMemory = Runtime.getRuntime().freeMemory(); whenLowMemorySet = System.currentTimeMillis(); } } } /** * Return true if a low memory water mark has been set and the current free * memory is lower than it. Otherwise return false. */ public boolean isLowMemory() { synchronized (this) { long lm = lowMemory; if (lm == 0) return false; if (Runtime.getRuntime().freeMemory() > lm) return false; // Only allow an low memory watermark to be valid // for five seconds after it was set. This stops // an incorrect limit being set for ever. This could // occur if other threads were freeing memory when // we called Runtime.getRuntime().freeMemory() long now = System.currentTimeMillis(); if ((now - this.whenLowMemorySet) > 5000L) { lowMemory = 0L; whenLowMemorySet = 0L; return false; } return true; } } }