]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics/src/org/simantics/MemoryWarningSystem.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics / src / org / simantics / MemoryWarningSystem.java
diff --git a/bundles/org.simantics/src/org/simantics/MemoryWarningSystem.java b/bundles/org.simantics/src/org/simantics/MemoryWarningSystem.java
new file mode 100644 (file)
index 0000000..1a46805
--- /dev/null
@@ -0,0 +1,130 @@
+package org.simantics;\r
+\r
+import java.lang.management.ManagementFactory;\r
+import java.lang.management.MemoryPoolMXBean;\r
+import java.lang.management.MemoryType;\r
+import java.util.Collection;\r
+import java.util.concurrent.CopyOnWriteArrayList;\r
+import java.util.concurrent.ScheduledFuture;\r
+import java.util.concurrent.TimeUnit;\r
+\r
+/**\r
+ * This memory warning system will call the listener when we exceed the\r
+ * percentage of available memory specified. There should only be one instance\r
+ * of this object created, since the usage threshold can only be set to one\r
+ * number.\r
+ * \r
+ * ( adapted from http://www.javaspecialists.eu/archive/Issue092.html )\r
+ * \r
+ * @author Antti Villberg\r
+ */\r
+public class MemoryWarningSystem {\r
+\r
+    public interface MemoryWarningListener {\r
+        void memoryLow(long usedMemory);\r
+    }\r
+\r
+    private final Collection<MemoryWarningListener> listeners = new CopyOnWriteArrayList<MemoryWarningListener>();\r
+\r
+    private static final MemoryPoolMXBean tenuredGenPool = findTenuredGenPool();\r
+\r
+    private double percentage = 1.0;\r
+\r
+    private ScheduledFuture<?> future;\r
+\r
+    private boolean disposed = false;\r
+\r
+    public MemoryWarningSystem(int amount, TimeUnit unit) {\r
+//        MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();\r
+//        NotificationEmitter emitter = (NotificationEmitter) mbean;\r
+//        emitter.addNotificationListener(new NotificationListener() {\r
+//            @Override\r
+//            public void handleNotification(Notification n, Object hb) {\r
+//                if (n.getType().equals(\r
+//                        MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED)) {\r
+//                     if(!check()) {\r
+//                             long used = getUsed();\r
+//                             for (MemoryWarningListener listener : listeners) {\r
+//                                     listener.memoryLow(used);\r
+//                             }\r
+//                     }\r
+//                     setPercentageUsageThreshold(percentage);\r
+//                }\r
+//            }\r
+//        }, null, null);\r
+\r
+       future = Simantics.scheduleAtFixedRate(new Runnable() {\r
+\r
+               @Override\r
+               public void run() {\r
+                       if(!disposed && !check()) {\r
+                               long bytes = get();\r
+                               for (MemoryWarningListener listener : listeners) {\r
+                                       listener.memoryLow(bytes);\r
+                               }\r
+                       }\r
+               }\r
+\r
+       }, 0, amount, unit);\r
+\r
+    }\r
+    \r
+    public long get() {\r
+       return tenuredGenPool.getUsage().getUsed();\r
+    }\r
+    \r
+    public boolean check() {\r
+       long max = Runtime.getRuntime().maxMemory();\r
+       long usedMemory = get();\r
+       long threshold = (long)(max * percentage);\r
+       return usedMemory < threshold;\r
+    }\r
+    \r
+    public long getUsed() {\r
+       return tenuredGenPool.getUsage().getUsed();\r
+    }\r
+\r
+    public boolean addListener(MemoryWarningListener listener) {\r
+        return listeners.add(listener);\r
+    }\r
+\r
+    public boolean removeListener(MemoryWarningListener listener) {\r
+        return listeners.remove(listener);\r
+    }\r
+\r
+    public void setPercentageUsageThreshold(double percentage) {\r
+        if (percentage <= 0.0 || percentage > 1.0) {\r
+            throw new IllegalArgumentException("Percentage not in range");\r
+        }\r
+       this.percentage = percentage;\r
+//        long maxMemory = Runtime.getRuntime().maxMemory();\r
+//        long warningThreshold = (long) (maxMemory * percentage);\r
+//        tenuredGenPool.setUsageThreshold(0);\r
+//        tenuredGenPool.setUsageThreshold(warningThreshold);\r
+    }\r
+\r
+    /**\r
+     * Tenured Space Pool can be determined by it being of type HEAP and by it\r
+     * being possible to set the usage threshold.\r
+     */\r
+    private static MemoryPoolMXBean findTenuredGenPool() {\r
+        for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {\r
+            // I don't know whether this approach is better, or whether\r
+            // we should rather check for the pool name "Tenured Gen"?\r
+            if (pool.getType() == MemoryType.HEAP\r
+                    && pool.isUsageThresholdSupported()) {\r
+                return pool;\r
+            }\r
+        }\r
+        throw new IllegalStateException("Could not find tenured space");\r
+    }\r
+\r
+    public void dispose() {\r
+        if (!disposed) {\r
+            disposed = true;\r
+            future.cancel(false);\r
+            listeners.clear();\r
+       }\r
+    }\r
+\r
+}
\ No newline at end of file