]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics/src/org/simantics/MemoryWarningSystem.java
Include acorn db in db.client feature and make it the default db driver
[simantics/platform.git] / bundles / org.simantics / src / org / simantics / MemoryWarningSystem.java
1 package org.simantics;\r
2 \r
3 import java.lang.management.ManagementFactory;\r
4 import java.lang.management.MemoryPoolMXBean;\r
5 import java.lang.management.MemoryType;\r
6 import java.util.Collection;\r
7 import java.util.concurrent.CopyOnWriteArrayList;\r
8 import java.util.concurrent.ScheduledFuture;\r
9 import java.util.concurrent.TimeUnit;\r
10 \r
11 /**\r
12  * This memory warning system will call the listener when we exceed the\r
13  * percentage of available memory specified. There should only be one instance\r
14  * of this object created, since the usage threshold can only be set to one\r
15  * number.\r
16  * \r
17  * ( adapted from http://www.javaspecialists.eu/archive/Issue092.html )\r
18  * \r
19  * @author Antti Villberg\r
20  */\r
21 public class MemoryWarningSystem {\r
22 \r
23     public interface MemoryWarningListener {\r
24         void memoryLow(long usedMemory);\r
25     }\r
26 \r
27     private final Collection<MemoryWarningListener> listeners = new CopyOnWriteArrayList<MemoryWarningListener>();\r
28 \r
29     private static final MemoryPoolMXBean tenuredGenPool = findTenuredGenPool();\r
30 \r
31     private double percentage = 1.0;\r
32 \r
33     private ScheduledFuture<?> future;\r
34 \r
35     private boolean disposed = false;\r
36 \r
37     public MemoryWarningSystem(int amount, TimeUnit unit) {\r
38 //        MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();\r
39 //        NotificationEmitter emitter = (NotificationEmitter) mbean;\r
40 //        emitter.addNotificationListener(new NotificationListener() {\r
41 //            @Override\r
42 //            public void handleNotification(Notification n, Object hb) {\r
43 //                if (n.getType().equals(\r
44 //                        MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED)) {\r
45 //                      if(!check()) {\r
46 //                              long used = getUsed();\r
47 //                              for (MemoryWarningListener listener : listeners) {\r
48 //                                      listener.memoryLow(used);\r
49 //                              }\r
50 //                      }\r
51 //                      setPercentageUsageThreshold(percentage);\r
52 //                }\r
53 //            }\r
54 //        }, null, null);\r
55 \r
56         future = Simantics.scheduleAtFixedRate(new Runnable() {\r
57 \r
58                 @Override\r
59                 public void run() {\r
60                         if(!disposed && !check()) {\r
61                                 long bytes = get();\r
62                                 for (MemoryWarningListener listener : listeners) {\r
63                                         listener.memoryLow(bytes);\r
64                                 }\r
65                         }\r
66                 }\r
67 \r
68         }, 0, amount, unit);\r
69 \r
70     }\r
71     \r
72     public long get() {\r
73         return tenuredGenPool.getUsage().getUsed();\r
74     }\r
75     \r
76     public boolean check() {\r
77         long max = Runtime.getRuntime().maxMemory();\r
78         long usedMemory = get();\r
79         long threshold = (long)(max * percentage);\r
80         return usedMemory < threshold;\r
81     }\r
82     \r
83     public long getUsed() {\r
84         return tenuredGenPool.getUsage().getUsed();\r
85     }\r
86 \r
87     public boolean addListener(MemoryWarningListener listener) {\r
88         return listeners.add(listener);\r
89     }\r
90 \r
91     public boolean removeListener(MemoryWarningListener listener) {\r
92         return listeners.remove(listener);\r
93     }\r
94 \r
95     public void setPercentageUsageThreshold(double percentage) {\r
96         if (percentage <= 0.0 || percentage > 1.0) {\r
97             throw new IllegalArgumentException("Percentage not in range");\r
98         }\r
99         this.percentage = percentage;\r
100 //        long maxMemory = Runtime.getRuntime().maxMemory();\r
101 //        long warningThreshold = (long) (maxMemory * percentage);\r
102 //        tenuredGenPool.setUsageThreshold(0);\r
103 //        tenuredGenPool.setUsageThreshold(warningThreshold);\r
104     }\r
105 \r
106     /**\r
107      * Tenured Space Pool can be determined by it being of type HEAP and by it\r
108      * being possible to set the usage threshold.\r
109      */\r
110     private static MemoryPoolMXBean findTenuredGenPool() {\r
111         for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {\r
112             // I don't know whether this approach is better, or whether\r
113             // we should rather check for the pool name "Tenured Gen"?\r
114             if (pool.getType() == MemoryType.HEAP\r
115                     && pool.isUsageThresholdSupported()) {\r
116                 return pool;\r
117             }\r
118         }\r
119         throw new IllegalStateException("Could not find tenured space");\r
120     }\r
121 \r
122     public void dispose() {\r
123         if (!disposed) {\r
124             disposed = true;\r
125             future.cancel(false);\r
126             listeners.clear();\r
127        }\r
128     }\r
129 \r
130 }