View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
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 org.apache.hadoop.classification.InterfaceAudience;
30  import org.apache.hadoop.classification.InterfaceStability;
31  
32  import com.google.common.base.Preconditions;
33  
34  @InterfaceAudience.Private
35  @InterfaceStability.Evolving
36  public class DirectMemoryUtils {
37    /**
38     * @return the setting of -XX:MaxDirectMemorySize as a long. Returns 0 if
39     *         -XX:MaxDirectMemorySize is not set.
40     */
41  
42    public static long getDirectMemorySize() {
43      RuntimeMXBean RuntimemxBean = ManagementFactory.getRuntimeMXBean();
44      List<String> arguments = RuntimemxBean.getInputArguments();
45      long multiplier = 1; //for the byte case.
46      for (String s : arguments) {
47        if (s.contains("-XX:MaxDirectMemorySize=")) {
48          String memSize = s.toLowerCase()
49              .replace("-xx:maxdirectmemorysize=", "").trim();
50  
51          if (memSize.contains("k")) {
52            multiplier = 1024;
53          }
54  
55          else if (memSize.contains("m")) {
56            multiplier = 1048576;
57          }
58  
59          else if (memSize.contains("g")) {
60            multiplier = 1073741824;
61          }
62          memSize = memSize.replaceAll("[^\\d]", "");
63  
64          long retValue = Long.parseLong(memSize);
65          return retValue * multiplier;
66        }
67  
68      }
69      return 0;
70    }
71  
72    /**
73     * DirectByteBuffers are garbage collected by using a phantom reference and a
74     * reference queue. Every once a while, the JVM checks the reference queue and
75     * cleans the DirectByteBuffers. However, as this doesn't happen
76     * immediately after discarding all references to a DirectByteBuffer, it's
77     * easy to OutOfMemoryError yourself using DirectByteBuffers. This function
78     * explicitly calls the Cleaner method of a DirectByteBuffer.
79     * 
80     * @param toBeDestroyed
81     *          The DirectByteBuffer that will be "cleaned". Utilizes reflection.
82     *          
83     */
84    public static void destroyDirectByteBuffer(ByteBuffer toBeDestroyed)
85        throws IllegalArgumentException, IllegalAccessException,
86        InvocationTargetException, SecurityException, NoSuchMethodException {
87  
88      Preconditions.checkArgument(toBeDestroyed.isDirect(),
89          "toBeDestroyed isn't direct!");
90  
91      Method cleanerMethod = toBeDestroyed.getClass().getMethod("cleaner");
92      cleanerMethod.setAccessible(true);
93      Object cleaner = cleanerMethod.invoke(toBeDestroyed);
94      Method cleanMethod = cleaner.getClass().getMethod("clean");
95      cleanMethod.setAccessible(true);
96      cleanMethod.invoke(cleaner);
97  
98    }
99  }