1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.util;
21
22 import java.lang.management.ManagementFactory;
23 import java.lang.management.RuntimeMXBean;
24 import java.lang.reflect.InvocationTargetException;
25 import java.lang.reflect.Method;
26 import java.nio.ByteBuffer;
27 import java.util.List;
28 import java.util.Locale;
29
30 import javax.management.JMException;
31 import javax.management.MBeanServer;
32 import javax.management.MalformedObjectNameException;
33 import javax.management.ObjectName;
34
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.apache.hadoop.hbase.classification.InterfaceAudience;
38 import org.apache.hadoop.hbase.classification.InterfaceStability;
39
40 import com.google.common.base.Preconditions;
41
42
43
44
45 @InterfaceAudience.Private
46 @InterfaceStability.Evolving
47 public class DirectMemoryUtils {
48 private static final Log LOG = LogFactory.getLog(DirectMemoryUtils.class);
49 private static final String MEMORY_USED = "MemoryUsed";
50 private static final MBeanServer BEAN_SERVER;
51 private static final ObjectName NIO_DIRECT_POOL;
52 private static final boolean HAS_MEMORY_USED_ATTRIBUTE;
53
54 static {
55
56
57 ObjectName n = null;
58 MBeanServer s = null;
59 Object a = null;
60 try {
61 n = new ObjectName("java.nio:type=BufferPool,name=direct");
62 } catch (MalformedObjectNameException e) {
63 LOG.warn("Unable to initialize ObjectName for DirectByteBuffer allocations.");
64 } finally {
65 NIO_DIRECT_POOL = n;
66 }
67 if (NIO_DIRECT_POOL != null) {
68 s = ManagementFactory.getPlatformMBeanServer();
69 }
70 BEAN_SERVER = s;
71 if (BEAN_SERVER != null) {
72 try {
73 a = BEAN_SERVER.getAttribute(NIO_DIRECT_POOL, MEMORY_USED);
74 } catch (JMException e) {
75 LOG.debug("Failed to retrieve nio.BufferPool direct MemoryUsed attribute: " + e);
76 }
77 }
78 HAS_MEMORY_USED_ATTRIBUTE = a != null;
79 }
80
81
82
83
84
85 public static long getDirectMemorySize() {
86 RuntimeMXBean runtimemxBean = ManagementFactory.getRuntimeMXBean();
87 List<String> arguments = runtimemxBean.getInputArguments();
88 long multiplier = 1;
89 for (String s : arguments) {
90 if (s.contains("-XX:MaxDirectMemorySize=")) {
91 String memSize = s.toLowerCase(Locale.ROOT)
92 .replace("-xx:maxdirectmemorysize=", "").trim();
93
94 if (memSize.contains("k")) {
95 multiplier = 1024;
96 }
97
98 else if (memSize.contains("m")) {
99 multiplier = 1048576;
100 }
101
102 else if (memSize.contains("g")) {
103 multiplier = 1073741824;
104 }
105 memSize = memSize.replaceAll("[^\\d]", "");
106
107 long retValue = Long.parseLong(memSize);
108 return retValue * multiplier;
109 }
110 }
111 return 0;
112 }
113
114
115
116
117 public static long getDirectMemoryUsage() {
118 if (BEAN_SERVER == null || NIO_DIRECT_POOL == null || !HAS_MEMORY_USED_ATTRIBUTE) return 0;
119 try {
120 Long value = (Long) BEAN_SERVER.getAttribute(NIO_DIRECT_POOL, MEMORY_USED);
121 return value == null ? 0 : value;
122 } catch (JMException e) {
123
124 return 0;
125 }
126 }
127
128
129
130
131
132
133
134
135
136
137
138
139
140 public static void destroyDirectByteBuffer(ByteBuffer toBeDestroyed)
141 throws IllegalArgumentException, IllegalAccessException,
142 InvocationTargetException, SecurityException, NoSuchMethodException {
143
144 Preconditions.checkArgument(toBeDestroyed.isDirect(),
145 "toBeDestroyed isn't direct!");
146
147 Method cleanerMethod = toBeDestroyed.getClass().getMethod("cleaner");
148 cleanerMethod.setAccessible(true);
149 Object cleaner = cleanerMethod.invoke(toBeDestroyed);
150 Method cleanMethod = cleaner.getClass().getMethod("clean");
151 cleanMethod.setAccessible(true);
152 cleanMethod.invoke(cleaner);
153 }
154 }