View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.common.utility;
21  
22  import io.netty.util.internal.SystemPropertyUtil;
23  
24  /**
25   * Utility that detects various properties specific to the current runtime
26   * environment, such as Java version.
27   */
28  public final class DetectionUtils {
29    private static final int JAVA_VERSION = javaVersion0();
30    private static final boolean IS_WINDOWS;
31    private static final boolean IS_UNIX_IBM;
32    private static final int NUMBERTHREAD;
33  
34    static {
35      final String os = SystemPropertyUtil.get("os.name").toLowerCase();
36      // windows
37      IS_WINDOWS = os.contains("win");
38      if (!IS_WINDOWS) {
39        String vendor = SystemPropertyUtil.get("java.vm.vendor");
40        vendor = vendor.toLowerCase();
41        IS_UNIX_IBM = vendor.contains("ibm");
42      } else {
43        IS_UNIX_IBM = false;
44      }
45      NUMBERTHREAD = Math.max(1, SystemPropertyUtil.getInt("org.waarp.numThreads",
46                                                           Runtime.getRuntime()
47                                                                  .availableProcessors() *
48                                                           2));
49    }
50  
51    private DetectionUtils() {
52    }
53  
54    /**
55     * @return the default number of threads (core * 2)
56     */
57    public static int numberThreads() {
58      return NUMBERTHREAD;
59    }
60  
61    /**
62     * Return {@code true} if the JVM is running on Windows
63     */
64    public static boolean isWindows() {
65      return IS_WINDOWS;
66    }
67  
68    /**
69     * Return {@code true} if the JVM is running on IBM UNIX JVM
70     */
71    public static boolean isUnixIBM() {
72      return IS_UNIX_IBM;
73    }
74  
75    public static int javaVersion() {
76      return JAVA_VERSION;
77    }
78  
79    private static boolean isAndroid0() {
80      // Idea: Sometimes java binaries include Android classes on the classpath, even if it isn't actually Android.
81      // Rather than check if certain classes are present, just check the VM, which is tied to the JDK.
82  
83      // Optional improvement: check if `android.os.Build.VERSION` is >= 24. On later versions of Android, the
84      // OpenJDK is used, which means `Unsafe` will actually work as expected.
85  
86      // Android sets this property to Dalvik, regardless of whether it actually is.
87      final String vmName = SystemPropertyUtil.get("java.vm.name");
88      return "Dalvik".equals(vmName);
89    }
90  
91    private static int javaVersion0() {
92      final int majorVersion;
93  
94      if (isAndroid0()) {
95        majorVersion = 6;
96      } else {
97        majorVersion = majorVersionFromJavaSpecificationVersion();
98      }
99  
100     return majorVersion;
101   }
102 
103   // Package-private for testing only
104   static int majorVersionFromJavaSpecificationVersion() {
105     return majorVersion(
106         SystemPropertyUtil.get("java.specification.version", "1.6"));
107   }
108 
109   // Package-private for testing only
110   static int majorVersion(final String javaSpecVersion) {
111     final String[] components = javaSpecVersion.split("\\.");
112     final int[] version = new int[components.length];
113     for (int i = 0; i < components.length; i++) {
114       version[i] = Integer.parseInt(components[i]);
115     }
116 
117     if (version[0] == 1) {
118       assert version[1] >= 6;
119       return version[1];
120     } else {
121       return version[0];
122     }
123   }
124 }