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