package net.i2p.util; /* * public domain */ import java.lang.reflect.Field; import java.util.TimeZone; import net.i2p.I2PAppContext; /** * Methods to find out what system we are running on * * @since 0.9.3 consolidated from various places */ public abstract class SystemVersion { /* * @since 0.9.28 */ public static final String DAEMON_USER = "i2psvc"; /* * @since 0.9.29 */ public static final String GENTOO_USER = "i2p"; private static final boolean _isWin = System.getProperty("os.name").startsWith("Win"); private static final boolean _isMac = System.getProperty("os.name").startsWith("Mac"); private static final boolean _isArm = System.getProperty("os.arch").startsWith("arm"); private static final boolean _isX86 = System.getProperty("os.arch").contains("86") || System.getProperty("os.arch").equals("amd64"); private static final boolean _isGentoo = System.getProperty("os.version").contains("gentoo") || System.getProperty("os.version").contains("hardened"); // Funtoo private static final boolean _isAndroid; private static final boolean _isApache; private static final boolean _isGNU; private static final boolean _isOpenJDK; private static final boolean _is64; private static final boolean _hasWrapper = System.getProperty("wrapper.version") != null; private static final boolean _isLinuxService; private static final boolean _isSlow; private static final boolean _oneDotSix; private static final boolean _oneDotSeven; private static final boolean _oneDotEight; private static final boolean _oneDotNine; private static final int _androidSDK; static { boolean is64 = "64".equals(System.getProperty("sun.arch.data.model")) || System.getProperty("os.arch").contains("64"); if (_isWin && !is64) { // http://stackoverflow.com/questions/4748673/how-can-i-check-the-bitness-of-my-os-using-java-j2se-not-os-arch // http://blogs.msdn.com/b/david.wang/archive/2006/03/26/howto-detect-process-bitness.aspx String arch = System.getenv("PROCESSOR_ARCHITECTURE"); String wow64Arch = System.getenv("PROCESSOR_ARCHITEW6432"); is64 = (arch != null && arch.endsWith("64")) || (wow64Arch != null && wow64Arch.endsWith("64")); } _is64 = is64; String vendor = System.getProperty("java.vendor"); _isAndroid = vendor.contains("Android"); _isApache = vendor.startsWith("Apache"); _isGNU = vendor.startsWith("GNU Classpath") || // JamVM vendor.startsWith("Free Software Foundation"); // gij String runtime = System.getProperty("java.runtime.name"); _isOpenJDK = runtime != null && runtime.contains("OpenJDK"); _isLinuxService = !_isWin && !_isMac && !_isAndroid && (DAEMON_USER.equals(System.getProperty("user.name")) || (_isGentoo && GENTOO_USER.equals(System.getProperty("user.name")))); _isSlow = _isAndroid || _isApache || _isArm || _isGNU || getMaxMemory() < 48*1024*1024L; int sdk = 0; if (_isAndroid) { try { Class<?> ver = Class.forName("android.os.Build$VERSION", true, ClassLoader.getSystemClassLoader()); Field field = ver.getField("SDK_INT"); sdk = field.getInt(null); } catch (Exception e) {} } _androidSDK = sdk; if (_isAndroid) { _oneDotSix = _androidSDK >= 9; _oneDotSeven = _androidSDK >= 19; // https://developer.android.com/guide/platform/j8-jack.html // some stuff in 23, some in 24 _oneDotEight = false; _oneDotNine = false; } else { String version = System.getProperty("java.version"); // handle versions like "8-ea" or "9-internal" if (!version.startsWith("1.")) version = "1." + version; _oneDotSix = VersionComparator.comp(version, "1.6") >= 0; _oneDotSeven = _oneDotSix && VersionComparator.comp(version, "1.7") >= 0; _oneDotEight = _oneDotSeven && VersionComparator.comp(version, "1.8") >= 0; _oneDotNine = _oneDotEight && VersionComparator.comp(version, "1.9") >= 0; } } public static boolean isWindows() { return _isWin; } public static boolean isMac() { return _isMac; } public static boolean isAndroid() { return _isAndroid; } /** * Apache Harmony JVM, or Android */ public static boolean isApache() { return _isApache || _isAndroid; } /** * gij or JamVM with GNU Classpath */ public static boolean isGNU() { return _isGNU; } /** * @since 0.9.23 */ public static boolean isGentoo() { return _isGentoo; } /** * @since 0.9.26 */ public static boolean isOpenJDK() { return _isOpenJDK; } /** * @since 0.9.8 */ public static boolean isARM() { return _isArm; } /** * @since 0.9.14 */ public static boolean isX86() { return _isX86; } /** * Our best guess on whether this is a slow architecture / OS / JVM, * using some simple heuristics. * * @since 0.9.30 */ public static boolean isSlow() { // we don't put the NBI call in the static field, // to prevent a circular initialization with NBI. return _isSlow || !NativeBigInteger.isNative(); } /** * Better than (new VersionComparator()).compare(System.getProperty("java.version"), "1.6") >= 0 * as it handles Android also, where java.version = "0". * * @return true if Java 1.6 or higher, or Android API 9 or higher */ public static boolean isJava6() { return _oneDotSix; } /** * Better than (new VersionComparator()).compare(System.getProperty("java.version"), "1.7") >= 0 * as it handles Android also, where java.version = "0". * * @return true if Java 1.7 or higher, or Android API 19 or higher * @since 0.9.14 */ public static boolean isJava7() { return _oneDotSeven; } /** * * @return true if Java 1.8 or higher, false for Android. * @since 0.9.15 */ public static boolean isJava8() { return _oneDotEight; } /** * * @return true if Java 1.9 or higher, false for Android. * @since 0.9.23 */ public static boolean isJava9() { return _oneDotNine; } /** * This isn't always correct. * http://stackoverflow.com/questions/807263/how-do-i-detect-which-kind-of-jre-is-installed-32bit-vs-64bit * http://mark.koli.ch/2009/10/javas-osarch-system-property-is-the-bitness-of-the-jre-not-the-operating-system.html * http://mark.koli.ch/2009/10/reliably-checking-os-bitness-32-or-64-bit-on-windows-with-a-tiny-c-app.html * sun.arch.data.model not on all JVMs * sun.arch.data.model == 64 => 64 bit processor * sun.arch.data.model == 32 => A 32 bit JVM but could be either 32 or 64 bit processor or libs * os.arch contains "64" could be 32 or 64 bit libs */ public static boolean is64Bit() { return _is64; } /* * @since 0.9.28 */ public static boolean isLinuxService() { return _isLinuxService; } /** * Identical to android.os.Build.VERSION.SDK_INT. * For use outside of Android code. * @return The SDK (API) version, e.g. 8 for Froyo, 0 if unknown */ public static int getAndroidVersion() { return _androidSDK; } /** * Is the wrapper present? * Same as I2PAppContext.hasWrapper() */ public static boolean hasWrapper() { return _hasWrapper; } /** * Runtime.getRuntime().maxMemory() but check for * bogus values * @since 0.9.8 */ public static long getMaxMemory() { long maxMemory = Runtime.getRuntime().maxMemory(); if (maxMemory >= Long.MAX_VALUE / 2) maxMemory = 96*1024*1024l; return maxMemory; } /** * The system's time zone, which is probably different from the * JVM time zone, because Router changes the JVM default to GMT. * It saves the old default in the context properties where we can get it. * Use this to format a time in local time zone with DateFormat.setTimeZone(). * * @return non-null * @since 0.9.24 */ public static TimeZone getSystemTimeZone() { return getSystemTimeZone(I2PAppContext.getGlobalContext()); } /** * The system's time zone, which is probably different from the * JVM time zone, because Router changes the JVM default to GMT. * It saves the old default in the context properties where we can get it. * Use this to format a time in local time zone with DateFormat.setTimeZone(). * * @return non-null * @since 0.9.24 */ public static TimeZone getSystemTimeZone(I2PAppContext ctx) { String systemTimeZone = ctx.getProperty("i2p.systemTimeZone"); if (systemTimeZone != null) return TimeZone.getTimeZone(systemTimeZone); return TimeZone.getDefault(); } /** * @since 0.9.24 */ public static void main(String[] args) { System.out.println("64 bit : " + is64Bit()); System.out.println("Java 6 : " + isJava6()); System.out.println("Java 7 : " + isJava7()); System.out.println("Java 8 : " + isJava8()); System.out.println("Java 9 : " + isJava9()); System.out.println("Android : " + isAndroid()); if (isAndroid()) System.out.println(" Version: " + getAndroidVersion()); System.out.println("Apache : " + isApache()); System.out.println("ARM : " + isARM()); System.out.println("Gentoo : " + isGentoo()); System.out.println("GNU : " + isGNU()); System.out.println("Linux Svc: " + isLinuxService()); System.out.println("Mac : " + isMac()); System.out.println("OpenJDK : " + isOpenJDK()); System.out.println("Slow : " + isSlow()); System.out.println("Windows : " + isWindows()); System.out.println("Wrapper : " + hasWrapper()); System.out.println("x86 : " + isX86()); System.out.println("Max mem : " + getMaxMemory()); } }