View Javadoc

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