8000 Fixed stale status of JVM on shut down (very rare) · githubcs/orientdb@09e7f83 · GitHub
[go: up one dir, main page]

Skip to content

Commit 09e7f83

Browse files
committed
Fixed stale status of JVM on shut down (very rare)
1 parent ec7778d commit 09e7f83

File tree

2 files changed

+93
-86
lines changed

2 files changed

+93
-86
lines changed

core/src/main/java/com/orientechnologies/orient/core/Orient.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,8 @@ public Orient shutdown() {
211211
profiler.shutdown();
212212

213213
if (memoryWatchDog != null) {
214-
// SHUTDOWN IT AND WAIT FOR COMPLETITION
215-
memoryWatchDog.interrupt();
214+
// SHUTDOWN IT AND WAIT FOR COMPETITION
215+
memoryWatchDog.sendShutdown();
216216
try {
217217
memoryWatchDog.join();
218218
} catch (InterruptedException e) {

core/src/main/java/com/orientechnologies/orient/core/memory/OMemoryWatchDog.java

Lines changed: 91 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,17 @@
1515
*/
1616
package com.orientechnologies.orient.core.memory;
1717

18+
import com.orientechnologies.common.io.OFileUtils;
19+
import com.orientechnologies.common.log.OLogManager;
20+
import com.orientechnologies.common.profiler.OAbstractProfiler.OProfilerHookValue;
21+
import com.orientechnologies.common.profiler.OProfilerMBean.METRIC_TYPE;
22+
import com.orientechnologies.orient.core.Orient;
23+
import com.orientechnologies.orient.core.config.OGlobalConfiguration;
24+
1825
import java.lang.management.ManagementFactory;
1926
import java.lang.management.MemoryMXBean;
2027
import java.lang.management.MemoryUsage;
28+
import java.lang.ref.Reference;
2129
import java.lang.ref.ReferenceQueue;
2230
import java.lang.ref.SoftReference;
2331
import java.util.ArrayList;
@@ -26,29 +34,33 @@
2634
import java.util.TimerTask;
2735
import java.util.WeakHashMap;
2836

29-
import com.orientechnologies.common.io.OFileUtils;
30-
import com.orientechnologies.common.log.OLogManager;
31-
import com.orientechnologies.common.profiler.OAbstractProfiler.OProfilerHookValue;
32-
import com.orientechnologies.common.profiler.OProfilerMBean.METRIC_TYPE;
33-
import com.orientechnologies.orient.core.Orient;
34-
import com.orientechnologies.orient.core.config.OGlobalConfiguration;
35-
3637
/**
3738
* This memory warning system will call the listener when we exceed the percentage of available memory specified. There should only
3839
* be one instance of this object created, since the usage threshold can only be set to one number.
3940
*/
4041
public class OMemoryWatchDog extends Thread {
41-
private final Map<ListenerWrapper, Object> listeners = new WeakHashMap<ListenerWrapper, Object>(128);
42-
private static long lastGC = 0;
43-
private int alertTimes = 0;
44-
protected final ReferenceQueue<Object> monitorQueue = new ReferenceQueue<Object>();
45-
protected SoftReference<Object> monitorRef = new SoftReference<Object>(new Object(), monitorQueue);
46-
42+
public static final int CHECK_TIMEOUT = 3000;
43+
private static long lastGC = 0;
44+
protected final ReferenceQueue<Object> monitorQueue = new ReferenceQueue<Object>();
45+
protected SoftReference<Object> monitorRef = new SoftReference<Object>(new Object(), monitorQueue);
4746
protected final MemoryMXBean memBean;
48-
47+
private final Map<ListenerWrapper, Object> listeners = new WeakHashMap<ListenerWrapper, Object>(128);
48+
private int alertTimes = 0;
4949
private long autoFreeCheckEveryMs;
5050
private long autoFreeHeapThreshold;
5151

52+
public static interface Listener {
53+
/**
54+
* Called when free memory is getting lower.
55+
*
56+
* @param iFreeMemory
57+
* Current used memory
58+
* @param iFreeMemoryPercentage
59+
* Max memory
60+
*/
61+
public void lowMemory(long iFreeMemory, long iFreeMemoryPercentage);
62+
}
63+
5264
/**
5365
* we want properties of both IdentityHashMap and WeakHashMap
5466
*/
@@ -84,22 +96,8 @@ public int hashCode() {
8496
}
8597
}
8698

87-
public static interface Listener {
88-
/**
89-
* Called when free memory is getting lower.
90-
*
91-
* @param iFreeMemory
92-
* Current used memory
93-
* @param iFreeMemoryPercentage
94-
* Max memory
95-
*/
96-
public void lowMemory(long iFreeMemory, long iFreeMemoryPercentage);
97-
}
98-
9999
/**
100100
* Create the memory watch dog with the default memory threshold.
101-
*
102-
* @param iThreshold
103101
*/
104102
public OMemoryWatchDog() {
105103
super("OrientDB MemoryWatchDog");
@@ -113,26 +111,49 @@ public OMemoryWatchDog() {
113111
start();
114112
}
115113

114+
public static void freeMemoryForOptimization(final long iDelayTime) {
115+
freeMemory(iDelayTime, OGlobalConfiguration.JVM_GC_DELAY_FOR_OPTIMIZE.getValueAsLong());
116+
}
117+
118+
public static void freeMemoryForResourceCleanup(final long iDelayTime) {
119+
freeMemory(iDelayTime, 0);
120+
}
121+
122+
private static void freeMemory(final long iDelayTime, final long minimalTimeAmount) {
123+
final long dateLastGC = System.currentTimeMillis();
124+
if (dateLastGC - lastGC > minimalTimeAmount * 1000) {
125+
lastGC = dateLastGC;
126+
System.gc();
127+
128+
if (iDelayTime > 0)
129+
try {
130+
Thread.sleep(iDelayTime);
131+
} catch (InterruptedException e) {
132+
Thread.currentThread().interrupt();
133+
}
134+
}
135+
}
136+
116137
@Override
117138
public void run() {
118139
Orient
119-
.instance()
120-
.getProfiler()
121-
.registerHookValue("system.memory.alerts", "Number of alerts received by JVM to free memory resources",
122-
METRIC_TYPE.COUNTER, new OProfilerHookValue() {
123-
public Object getValue() {
124-
return alertTimes;
125-
}
126-
});
140+
.instance()
141+
.getProfiler()
142+
.registerHookValue("system.memory.alerts", "Number of alerts received by JVM to free memory resources",
143+
METRIC_TYPE.COUNTER, new OProfilerHookValue() {
144+
public Object getValue() {
145+
return alertTimes;
146+
}
147+
});
127148
Orient
128-
.instance()
129-
.getProfiler()
130-
.registerHookValue("system.memory.lastGC", "Date of last System.gc() invocation", METRIC_TYPE.STAT,
131-
new OProfilerHookValue() {
132-
public Object getValue() {
133-
return lastGC;
134-
}
135-
});
149+
.instance()
150+
.getProfiler()
151+
.registerHookValue("system.memory.lastGC", "Date of last System.gc() invocation", METRIC_TYPE.STAT,
152+
new OProfilerHookValue() {
153+
public Object getValue() {
154+
return lastGC;
155+
}
156+
});
136157

137158
autoFreeCheckEveryMs = OGlobalConfiguration.MEMORY_AUTOFREE_CHECK_EVERY.getValueAsLong();
138159
Orient.instance().getTimer().schedule(new TimerTask() {
@@ -167,35 +188,38 @@ public void run() {
167188
while (true) {
168189
try {
169190
// WAITS FOR THE GC FREE
170-
monitorQueue.remove();
191+
final Reference<?> res = monitorQueue.remove(CHECK_TIMEOUT);
171192

193+
// CHECK IF HAS BEEN INTERRUPTED
172194
if (Thread.interrupted())
195+
// INTERRUPTED, EXIT FROM THE THREAD'S LOOP!
173196
break;
174197

175-
// GC is freeing memory!
176-
alertTimes++;
177-
MemoryUsage heapMemory = memBean.getHeapMemoryUsage();
178-
final long usedHeap = heapMemory.getUsed();
179-
final long maxHeap = heapMemory.getMax();
180-
final int usedMemoryPer = (int) (usedHeap * 100 / maxHeap);
198+
if (res != null) { // GC is freeing memory!
199+
alertTimes++;
200+
MemoryUsage heapMemory = memBean.getHeapMemoryUsage();
201+
final long usedHeap = heapMemory.getUsed();
202+
final long maxHeap = heapMemory.getMax();
203+
final int usedMemoryPer = (int) (usedHeap * 100 / maxHeap);
181204

182-
if (OLogManager.instance().isDebugEnabled())
183-
OLogManager.instance().debug(this, "Free memory is low %s of %s (%d%%), calling listeners to free memory...",
184-
OFileUtils.getSizeAsString(maxHeap - usedHeap), OFileUtils.getSizeAsString(maxHeap), 100 - usedMemoryPer);
205+
if (OLogManager.instance().isDebugEnabled())
206+
OLogManager.instance().debug(this, "Free memory is low %s of %s (%d%%), calling listeners to free memory...",
207+
OFileUtils.getSizeAsString(maxHeap - usedHeap), OFileUtils.getSizeAsString(maxHeap), 100 - usedMemoryPer);
185208

186-
final long timer = Orient.instance().getProfiler().startChrono();
209+
final long timer = Orient.instance().getProfiler().startChrono();
187210

188-
synchronized (listeners) {
189-
E377 for (ListenerWrapper listener : listeners.keySet()) {
190-
try {
191-
listener.listener.lowMemory(maxHeap - usedHeap, 100 - usedMemoryPer);
192-
} catch (Exception e) {
193-
e.printStackTrace();
211+
synchronized (listeners) {
212+
for (ListenerWrapper listener : listeners.keySet()) {
213+
try {
214+
listener.listener.lowMemory(maxHeap - usedHeap, 100 - usedMemoryPer);
215+
} catch (Exception e) {
216+
e.printStackTrace();
217+
}
194218
}
195219
}
196-
}
197220

198-
Orient.instance().getProfiler().stopChrono("OMemoryWatchDog.freeResources", "WatchDog free resources", timer);
221+
Orient.instance().getProfiler().stopChrono("OMemoryWatchDog.freeResources", "WatchDog free resources", timer);
222+
}
199223

200224
} catch (InterruptedException e) {
201225
break;
@@ -249,14 +273,6 @@ public List<Listener> getListeners() {
249273
}
250274
}
251275

252-
public static void freeMemoryForOptimization(final long iDelayTime) {
253-
freeMemory(iDelayTime, OGlobalConfiguration.JVM_GC_DELAY_FOR_OPTIMIZE.getValueAsLong());
254-
}
255-
256-
public static void freeMemoryForResourceCleanup(final long iDelayTime) {
257-
freeMemory(iDelayTime, 0);
258-
}
259-
260276
public long getUsedHeapMemory() {
261277
MemoryUsage heapMemory = memBean.getHeapMemoryUsage();
262278
return heapMemory.getUsed();
@@ -267,19 +283,10 @@ public int getUsedHeapMemoryInPercentage() {
267283
return (int) (heapMemory.getUsed() * 100 / heapMemory.getMax());
268284
}
269285

270-
private static void freeMemory(final long iDelayTime, final long minimalTimeAmount) {
271-
final long dateLastGC = System.currentTimeMillis();
272-
if (dateLastGC - lastGC > minimalTimeAmount * 1000) {
273-
lastGC = dateLastGC;
274-
System.gc();
275-
276-
if (iDelayTime > 0)
277-
try {
278-
Thread.sleep(iDelayTime);
279-
} catch (InterruptedException e) {
280-
Thread.currentThread().interrupt();
281-
}
286+
public void sendShutdown() {
287+
interrupt();
288+
synchronized (monitorQueue) {
289+
monitorQueue.notifyAll();
282290
}
283291
}
284-
285292
}

0 commit comments

Comments
 (0)
0