-
-
Notifications
You must be signed in to change notification settings - Fork 44
/
LeakDetector.java
69 lines (59 loc) · 2.09 KB
/
LeakDetector.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package me.nallar.reporting;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import me.nallar.tickthreading.Log;
import me.nallar.unsafe.UnsafeUtil;
public class LeakDetector {
private final Timer timer = new Timer("Leak Detector", true);
private final long waitTime;
private final Map<Long, LeakCheckEntry> scheduledObjects = new ConcurrentHashMap<Long, LeakCheckEntry>();
public LeakDetector(final long waitTimeSeconds) {
waitTime = waitTimeSeconds * 1000;
}
public void scheduleLeakCheck(Object o, String oDescription_, final boolean clean) {
if (clean) {
timer.schedule(new CleanerTask(o), Math.min(waitTime / 2, 60000));
}
final long id = UnsafeUtil.addressOf(o);
final String oDescription = (oDescription_ == null ? "" : oDescription_ + " : ") + o.getClass() + '@' + System.identityHashCode(o) + ':' + id;
scheduledObjects.put(id, new LeakCheckEntry(o, oDescription));
timer.schedule(new TimerTask() {
@Override
public void run() {
LeakCheckEntry leakCheckEntry = scheduledObjects.remove(id);
Object o = leakCheckEntry.o.get();
if (o == null) {
Log.fine("Object " + leakCheckEntry.description + " has been removed normally.");
} else {
String warning = "Probable memory leak detected. \"" + leakCheckEntry.description + "\" has not been garbage collected after " + waitTime / 1000 + "s.";
if (clean) {
Log.fine(warning);
} else {
Log.warning(warning);
}
}
}
}, waitTime);
}
private static class CleanerTask extends TimerTask {
final Object toClean;
CleanerTask(final Object toClean) {
this.toClean = toClean;
}
@Override
public void run() {
UnsafeUtil.clean(toClean);
}
}
private static class LeakCheckEntry {
public final WeakReference<Object> o;
public final String description;
LeakCheckEntry(final Object o, final String description) {
this.o = new WeakReference<Object>(o);
this.description = description;
}
}
}