View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.util;
19  
20  import java.lang.reflect.Field;
21  import java.lang.reflect.Method;
22  import java.security.AccessController;
23  import java.security.PrivilegedAction;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.hadoop.hbase.classification.InterfaceAudience;
28  
29  @InterfaceAudience.Private
30  public class UnsafeAvailChecker {
31  
32    private static final String CLASS_NAME = "sun.misc.Unsafe";
33    private static final Log LOG = LogFactory.getLog(UnsafeAvailChecker.class);
34    private static boolean avail = false;
35    private static boolean unaligned = false;
36  
37    static {
38      avail = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
39        @Override
40        public Boolean run() {
41          try {
42            Class<?> clazz = Class.forName(CLASS_NAME);
43            Field f = clazz.getDeclaredField("theUnsafe");
44            f.setAccessible(true);
45            return f.get(null) != null;
46          } catch (Throwable e) {
47            LOG.warn("sun.misc.Unsafe is not available/accessible", e);
48          }
49          return false;
50        }
51      });
52      // When Unsafe itself is not available/accessible consider unaligned as false.
53      if (avail) {
54        String arch = System.getProperty("os.arch");
55        if ("ppc64".equals(arch) || "ppc64le".equals(arch)) {
56          // java.nio.Bits.unaligned() wrongly returns false on ppc (JDK-8165231),
57          unaligned = true;
58        } else {
59          try {
60            // Using java.nio.Bits#unaligned() to check for unaligned-access capability
61            Class<?> clazz = Class.forName("java.nio.Bits");
62            Method m = clazz.getDeclaredMethod("unaligned");
63            m.setAccessible(true);
64            unaligned = (Boolean) m.invoke(null);
65          } catch (Exception e) {
66            LOG.warn("java.nio.Bits#unaligned() check failed."
67                + "Unsafe based read/write of primitive types won't be used", e);
68          }
69        }
70      }
71    }
72  
73    /**
74     * @return true when running JVM is having sun's Unsafe package available in it and it is
75     *         accessible.
76     */
77    public static boolean isAvailable() {
78      return avail;
79    }
80  
81    /**
82     * @return true when running JVM is having sun's Unsafe package available in it and underlying
83     *         system having unaligned-access capability.
84     */
85    public static boolean unaligned() {
86      return unaligned;
87    }
88  
89    private UnsafeAvailChecker() {
90      // private constructor to avoid instantiation
91    }
92  }