1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.devtools.util;
17
18 import java.lang.management.ManagementFactory;
19 import java.lang.management.MemoryMXBean;
20 import java.lang.management.MemoryNotificationInfo;
21 import java.lang.management.MemoryPoolMXBean;
22 import java.lang.management.MemoryType;
23 import java.util.ArrayList;
24 import java.util.Collection;
25
26 import javax.management.Notification;
27 import javax.management.NotificationEmitter;
28 import javax.management.NotificationListener;
29
30 import org.apache.log4j.Logger;
31
32 public class MemoryMonitor {
33 private final Collection<Listener> listeners = new ArrayList<Listener>();
34 private static final Logger LOG = Logger.getLogger(MemoryMonitor.class);
35 private String springContextId;
36
37 public interface Listener {
38 public void memoryUsageLow(String springContextId, long usedMemory, long maxMemory);
39 }
40
41 public MemoryMonitor() {
42 LOG.info("initializing");
43 this.springContextId = "Unknown";
44 MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();
45 NotificationEmitter emitter = (NotificationEmitter) mbean;
46 emitter.addNotificationListener(new NotificationListener() {
47 public void handleNotification(Notification n, Object hb) {
48 if (n.getType().equals(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED)) {
49 long maxMemory = tenuredGenPool.getUsage().getMax();
50 long usedMemory = tenuredGenPool.getUsage().getUsed();
51 for (Listener listener : listeners) {
52 listener.memoryUsageLow(springContextId, usedMemory, maxMemory);
53 }
54 }
55 }
56 }, null, null);
57 }
58
59 public MemoryMonitor(String springContextId) {
60 this();
61 this.springContextId = springContextId;
62 }
63
64 public boolean addListener(Listener listener) {
65 return listeners.add(listener);
66 }
67
68 public boolean removeListener(Listener listener) {
69 return listeners.remove(listener);
70 }
71
72 private static final MemoryPoolMXBean tenuredGenPool = findTenuredGenPool();
73
74 public static void setPercentageUsageThreshold(double percentage) {
75 if (percentage <= 0.0 || percentage > 1.0) {
76 throw new IllegalArgumentException("percentage not in range");
77 }
78 long maxMemory = tenuredGenPool.getUsage().getMax();
79 long warningThreshold = (long) (maxMemory * percentage);
80 tenuredGenPool.setUsageThreshold(warningThreshold);
81 }
82
83 private static MemoryPoolMXBean findTenuredGenPool() {
84 for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {
85 if (pool.getType() == MemoryType.HEAP && pool.isUsageThresholdSupported()) {
86 return pool;
87 }
88 }
89 throw new AssertionError("could not find tenured space");
90 }
91 }