View Javadoc

    1   /*
    2    * Copyright 2012 The Netty Project
    3    *
    4    * The Netty Project licenses this file to you under the Apache License,
    5    * version 2.0 (the "License"); you may not use this file except in compliance
    6    * with the License. You may obtain a copy of the License at:
    7    *
    8    *   http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    13   * License for the specific language governing permissions and limitations
    14   * under the License.
    15   */
    16  package org.jboss.netty.util.internal;
    17
    18  import java.security.AccessController;
    19  import java.security.PrivilegedActionException;
    20  import java.security.PrivilegedExceptionAction;
    21  import java.util.concurrent.atomic.AtomicInteger;
    22  import java.util.zip.Deflater;
    23
    24
    25  /**
    26   * Utility that detects various properties specific to the current runtime
    27   * environment, such as Java version and the availability of the
    28   * {@code sun.misc.Unsafe} object.
    29   *
    30   * <br>
    31   * You can disable the use of {@code sun.misc.Unsafe} if you specify
    32   * the System property <strong>org.jboss.netty.tryUnsafe</strong> with
    33   * value of <code>false</code>. Default is <code>true</code>.
    34   */
    35  public final class DetectionUtil {
    36
    37      private static final int JAVA_VERSION = javaVersion0();
    38      private static final boolean HAS_UNSAFE = hasUnsafe(AtomicInteger.class.getClassLoader());
    39      private static final boolean IS_WINDOWS;
    40      static {
    41          String os = System.getProperty("os.name").toLowerCase();
    42          // windows
    43          IS_WINDOWS =  os.indexOf("win") >= 0;
    44      }
    45
    46      /**
    47       * Return <code>true</code> if the JVM is running on Windows
    48       *
    49       */
    50      public static boolean isWindows() {
    51          return IS_WINDOWS;
    52      }
    53
    54      public static boolean hasUnsafe() {
    55          return HAS_UNSAFE;
    56      }
    57
    58      public static int javaVersion() {
    59          return JAVA_VERSION;
    60      }
    61
    62      private static boolean hasUnsafe(ClassLoader loader) {
    63          boolean useUnsafe = Boolean.valueOf(SystemPropertyUtil.get("org.jboss.netty.tryUnsafe", "true"));
    64          if (!useUnsafe) {
    65              return false;
    66          }
    67
    68          try {
    69              Class<?> unsafeClazz = Class.forName("sun.misc.Unsafe", true, loader);
    70              return hasUnsafeField(unsafeClazz);
    71          } catch (Exception e) {
    72              // Ignore
    73          }
    74          return false;
    75      }
    76
    77      private static boolean hasUnsafeField(final Class<?> unsafeClass) throws PrivilegedActionException {
    78          return AccessController.doPrivileged(new PrivilegedExceptionAction<Boolean>() {
    79              public Boolean run() throws Exception {
    80                  unsafeClass.getDeclaredField("theUnsafe");
    81                  return true;
    82              }
    83          });
    84      }
    85
    86      private static int javaVersion0() {
    87          try {
    88              // Check if its android, if so handle it the same way as java6.
    89              //
    90              // See https://github.com/netty/netty/issues/282
    91              Class.forName("android.app.Application");
    92              return 6;
    93          } catch (ClassNotFoundException e) {
    94              //Ignore
    95          }
    96
    97          try {
    98              Deflater.class.getDeclaredField("SYNC_FLUSH");
    99              return 7;
    100         } catch (Exception e) {
    101             // Ignore
    102         }
    103
    104         try {
    105             Double.class.getDeclaredField("MIN_NORMAL");
    106             return 6;
    107         } catch (Exception e) {
    108             // Ignore
    109         }
    110
    111         return 5;
    112     }
    113
    114     private DetectionUtil() {
    115         // only static method supported
    116     }
    117 }