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