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 }