java.lang.Object
net.i2p.util.SystemVersion

public abstract class SystemVersionextends Object
Methods to find out what system we are running on.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final int
    (package private) static final long
    Minimum interval between two OS queries for the process CPU load.
    static final String
    The account name a packaged Linux service runs the router under.
    static final boolean
    With no override configured, slow platforms are still detected automatically.
    static final String
    The account name the Gentoo package runs the router service under, which differs from the one the other distributions use.
    static final String
    Set to true to drop the single-core, low-memory term from isSlow(), so a small router can still be treated as fast.
    (package private) static final long
    Minimum interval between two OS queries for the system load average.
  • Constructor Summary

    Constructors
    Modifier
    Constructor
    Description
    protected
    The host environment the router runs on, as reported by the OS and JVM properties probed below.
  • Method Summary

    All Methods
    Modifier and Type
    Method
    Description
    static double
    buildSuccessRatio(double success, double reject, double expire)
    Successes over all settled builds.
    (package private) static boolean
    cpuLoadCacheStale(long lastQueried, long now)
    Whether the cached CPU load sample is old enough to refresh.
    static int
    Returns the current number of active (live) threads in the JVM.
    static int
    Identical to android.os.Build.VERSION.SDK_INT.
    static String
    Returns the architecture of the system running I2P as a string for reference in clients.config and plugin.config files.
    static int
    Total CPUs including parked/offline cores.
    static int
    Retrieve CPU Load of the JVM.
    static int
    Retrieve CPU Load Average of the JVM.
    static double
    60s-smoothed process CPU load expressed in cores, e.g.
    static long
    Runtime.getRuntime().maxMemory() but check for bogus values.
    static String
    Returns the OS of the system running I2P as a lower-case string for reference in clients.config and plugin.config files.
    static int
    Retrieve the system load as a percentage, where 100% equals full system load.
    static TimeZone
    The system's time zone, which is probably different from the JVM time zone, because Router changes the JVM default to GMT.
    static TimeZone
    The system's time zone, which is probably different from the JVM time zone, because Router changes the JVM default to GMT.
    static int
    Retrieve Tunnel build success as a percentage.
    static double
    The canonical tunnel build success ratio: successes over all settled builds, 0.0 to 1.0, for a stated window.
    static boolean
    Is the wrapper present? Same as I2PAppContext.hasWrapper().
    static boolean
    This isn't always correct.
    static boolean
    Whether the OS is Android.
    static boolean
    Apache Harmony JVM, or Android.
    static boolean
    Speed: do not cripple down for powerful ARM.
    static boolean
    True if Gentoo.
    static boolean
    Gij or JamVM with GNU Classpath.
    static boolean
    isJava(int minVersion)
    Handles Android also.
    static boolean
    isJava(String minVersion)
    Handles Android, and minVersions in both forms (e.g.
    static boolean
    True if the JVM is Java 10 or higher, false for Android.
    static boolean
    True if the JVM is Java 11 or higher, false for Android.
    static boolean
    True if the JVM is Java 12 or higher, false for Android.
    static boolean
    True if the JVM is Java 13 or higher, false for Android.
    static boolean
    True if the JVM is Java 14 or higher, false for Android.
    static boolean
    True if the JVM is Java 15 or higher, false for Android.
    static boolean
    True if the JVM is Java 16 or higher, false for Android.
    static boolean
    True if the JVM is Java 17 or higher, false for Android.
    static boolean
    True if the JVM is Java 18 or higher, false for Android.
    static boolean
    True if the JVM is Java 19 or higher, false for Android.
    static boolean
    True if the JVM is Java 20 or higher, false for Android.
    static boolean
    True if the JVM is Java 21 or higher, false for Android.
    static boolean
    True if the JVM is Java 22 or higher, false for Android.
    static boolean
    Better than (new VersionComparator()).compare(System.getProperty(String)"java.version"), "1.6") >= 0 as it handles Android also, where java.version = "0".
    static boolean
    Better than (new VersionComparator()).compare(System.getProperty(String)"java.version"), "1.7") >= 0 as it handles Android also, where java.version = "0".
    static boolean
    True if the JVM is Java 8 or higher, false for Android.
    static boolean
    True if the JVM is Java 9 or higher, false for Android.
    static boolean
    Whether running as a Linux service.
    static boolean
    Whether the OS is Mac.
    static boolean
    True if OpenJDK.
    static boolean
    Whether running as a service under either platform.
    static boolean
    Our best guess on whether this is a slow architecture / OS / JVM, using some simple heuristics.
    static boolean
    Whether the OS is Windows.
    static boolean
    Whether running as a Windows service.
    static boolean
    True if x86.
    static boolean
    Is this a very slow interpreted mode VM?
    static void
    main(String[] args)
    Print the Java version and VM this router is running under, for diagnosing a user-reported problem from the console output.
    (package private) static boolean
    sysLoadCacheStale(long lastQueried, long now)
    Whether the cached system load sample is old enough to refresh.
    static int
    Calculate how many (virtual) cores should be actually used by a thread pool.

    Methods inherited from class Object

    clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • DAEMON_USER

      public static final String DAEMON_USER
      The account name a packaged Linux service runs the router under.
      See Also:
    • GENTOO_USER

      public static final String GENTOO_USER
      The account name the Gentoo package runs the router service under, which differs from the one the other distributions use.
      See Also:
    • CPU_LOAD_CACHE_MS

      static final long CPU_LOAD_CACHE_MS
      Minimum interval between two OS queries for the process CPU load. Each query is expensive (on JDK 19+ the MXBean reads /proc via Files.lines), and the value is only used for coarse throttling/backoff, so a 1-second cache is plenty.
      See Also:
    • SYSTEM_LOAD_CACHE_MS

      static final long SYSTEM_LOAD_CACHE_MS
      Minimum interval between two OS queries for the system load average. getSystemLoadAverage() is a native call (JDK reads /proc/loadavg), far more expensive than a map lookup, and it sits on the per-build-request path of both tunnel throttlers. The load average is itself a 1/5/15 minute metric, so 1s of staleness is far below its own resolution.
      See Also:
    • PROP_OVERRIDE_IS_SLOW

      public static final String PROP_OVERRIDE_IS_SLOW
      Set to true to drop the single-core, low-memory term from isSlow(), so a small router can still be treated as fast. It gates only that term: the Android, ARM, GNU and Zero tests, the non-native BigInteger test, and the under-4-cores 32-bit test still apply.
      See Also:
    • DEFAULT_OVERRIDE_IS_SLOW

      public static final boolean DEFAULT_OVERRIDE_IS_SLOW
      With no override configured, slow platforms are still detected automatically.
      See Also:
    • BUILD_SUCCESS_WINDOW_MS

      public static final int BUILD_SUCCESS_WINDOW_MS
      Default window for getTunnelBuildSuccessRatio(StatManager, int). Ten minutes: long enough that a single bad minute is not mistaken for sustained failure, short enough to react within one LeaseSet refresh cycle.
      See Also:
  • Constructor Details

    • SystemVersion

      protected SystemVersion()
      The host environment the router runs on, as reported by the OS and JVM properties probed below. No state is held per instance; the probes are static and cache their own results.
  • Method Details

    • getOS

      public static String getOS()
      Returns the OS of the system running I2P as a lower-case string for reference in clients.config and plugin.config files.

      matches the conventions of the Go cross compiler.

      Returns:
      the OS of the system running I2P as a lower-case string
    • getArch

      public static String getArch()
      Returns the architecture of the system running I2P as a string for reference in clients.config and plugin.config files.

      matches the conventions of the Go cross compiler.

      Returns:
      the architecture of the system running I2P as a string
    • isWindows

      public static boolean isWindows()
      Whether the OS is Windows.
      Returns:
      true when os.name starts with "Win", resolved once at class load
    • isMac

      public static boolean isMac()
      Whether the OS is Mac.
      Returns:
      true when os.name starts with "Mac", resolved once at class load
    • isAndroid

      public static boolean isAndroid()
      Whether the OS is Android.
      Returns:
      true when java.vendor contains "Android"
    • isApache

      public static boolean isApache()
      Apache Harmony JVM, or Android.
      Returns:
      true when java.vendor starts with "Apache", or on Android
    • isGNU

      public static boolean isGNU()
      Gij or JamVM with GNU Classpath.
      Returns:
      whether GNU
    • isGentoo

      public static boolean isGentoo()
      True if Gentoo.
      Returns:
      true when os.version names gentoo or a hardened kernel
    • isOpenJDK

      public static boolean isOpenJDK()
      True if OpenJDK.
      Returns:
      whether open j d k
    • isARM

      public static boolean isARM()
      Speed: do not cripple down for powerful ARM.
      Returns:
      whether a r m
    • isX86

      public static boolean isX86()
      True if x86.
      Returns:
      whether x86
    • isZeroVM

      public static boolean isZeroVM()
      Is this a very slow interpreted mode VM?
      Returns:
      whether zero v m
    • isSlow

      public static boolean isSlow()
      Our best guess on whether this is a slow architecture / OS / JVM, using some simple heuristics.
      Returns:
      the cached verdict, OR-ed with a live core count, native big integer, and heap size check that is suppressed by the override property
    • isJava6

      public static boolean isJava6()
      Better than (new VersionComparator()).compare(System.getProperty(String)"java.version"), "1.6") >= 0 as it handles Android also, where java.version = "0".
      Returns:
      true if Java 1.6 or higher, or Android API 9 or higher
    • isJava7

      public static boolean isJava7()
      Better than (new VersionComparator()).compare(System.getProperty(String)"java.version"), "1.7") >= 0 as it handles Android also, where java.version = "0".
      Returns:
      true if Java 1.7 or higher, or Android API 19 or higher
    • isJava8

      public static boolean isJava8()
      True if the JVM is Java 8 or higher, false for Android.
      Returns:
      true if Java 1.8 or higher, false for Android.
    • isJava9

      public static boolean isJava9()
      True if the JVM is Java 9 or higher, false for Android.
      Returns:
      true if Java 9 or higher, false for Android.
    • isJava10

      public static boolean isJava10()
      True if the JVM is Java 10 or higher, false for Android.
      Returns:
      true if Java 10 or higher, false for Android.
    • isJava11

      public static boolean isJava11()
      True if the JVM is Java 11 or higher, false for Android.
      Returns:
      true if Java 11 or higher, false for Android.
    • isJava12

      public static boolean isJava12()
      True if the JVM is Java 12 or higher, false for Android.
      Returns:
      true if Java 12 or higher, false for Android.
    • isJava13

      public static boolean isJava13()
      True if the JVM is Java 13 or higher, false for Android.
      Returns:
      true if Java 13 or higher, false for Android.
    • isJava14

      public static boolean isJava14()
      True if the JVM is Java 14 or higher, false for Android.
      Returns:
      true if Java 14 or higher, false for Android.
    • isJava15

      public static boolean isJava15()
      True if the JVM is Java 15 or higher, false for Android.
      Returns:
      true if Java 15 or higher, false for Android.
    • isJava16

      public static boolean isJava16()
      True if the JVM is Java 16 or higher, false for Android.
      Returns:
      true if Java 16 or higher, false for Android.
    • isJava17

      public static boolean isJava17()
      True if the JVM is Java 17 or higher, false for Android.
      Returns:
      true if Java 17 or higher, false for Android.
    • isJava18

      public static boolean isJava18()
      True if the JVM is Java 18 or higher, false for Android.
      Returns:
      true if Java 18 or higher, false for Android.
    • isJava19

      public static boolean isJava19()
      True if the JVM is Java 19 or higher, false for Android.
      Returns:
      true if Java 19 or higher, false for Android.
    • isJava20

      public static boolean isJava20()
      True if the JVM is Java 20 or higher, false for Android.
      Returns:
      true if Java 20 or higher, false for Android.
    • isJava21

      public static boolean isJava21()
      True if the JVM is Java 21 or higher, false for Android.
      Returns:
      true if Java 21 or higher, false for Android.
    • isJava22

      public static boolean isJava22()
      True if the JVM is Java 22 or higher, false for Android.
      Returns:
      true if Java 21 or higher, false for Android.
    • isJava

      public static boolean isJava(int minVersion)
      Handles Android also.
      Parameters:
      minVersion - e.g. 11
      Returns:
      true if greater than or equal to minVersion
    • isJava

      public static boolean isJava(String minVersion)
      Handles Android, and minVersions in both forms (e.g. 11 or 1.11).
      Parameters:
      minVersion - either 1.x or x form works
      Returns:
      true if greater than or equal to minVersion
    • is64Bit

      public static boolean is64Bit()
      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.
      Returns:
      whether 64 bit
    • isLinuxService

      public static boolean isLinuxService()
      Whether running as a Linux service.
      Returns:
      whether linux service
    • isWindowsService

      public static boolean isWindowsService()
      Whether running as a Windows service.
      Returns:
      whether windows service
    • isService

      public static boolean isService()
      Whether running as a service under either platform.
      Returns:
      true for a Linux daemon user or a Tanuki wrapper on Windows
    • getAndroidVersion

      public static int getAndroidVersion()
      Identical to android.os.Build.VERSION.SDK_INT. For use outside of Android code.
      Returns:
      The SDK (API) version, e.g. 8 for Froyo, 0 if unknown
    • hasWrapper

      public static boolean hasWrapper()
      Is the wrapper present? Same as I2PAppContext.hasWrapper().
      Returns:
      whether wrapper is present
    • getMaxMemory

      public static long getMaxMemory()
      Runtime.getRuntime().maxMemory() but check for bogus values.
      Returns:
      the max memory
    • getCores

      public static int getCores()
      Total CPUs including parked/offline cores. On Linux, reads /sys/devices/system/cpu/present to get the full CPU topology regardless of cpufreq governor parking. Falls back to Runtime.getRuntime().availableProcessors().
      Returns:
      never smaller than 1
    • usableCores

      public static int usableCores()
      Calculate how many (virtual) cores should be actually used by a thread pool.
      Returns:
      1 on Windows and macOS, or 3/4 of the logical cores on x86
    • getSystemTimeZone

      public static TimeZone getSystemTimeZone()
      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().
      Returns:
      non-null
    • getSystemTimeZone

      public static TimeZone getSystemTimeZone(I2PAppContext ctx)
      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().
      Parameters:
      ctx - the application context whose properties hold the saved system time zone ID
      Returns:
      the saved system time zone, or the JVM default if none was saved
    • main

      public static void main(String[] args)
      Print the Java version and VM this router is running under, for diagnosing a user-reported problem from the console output.
      Parameters:
      args - ignored, no arguments are parsed
    • getCPULoad

      public static int getCPULoad()
      Retrieve CPU Load of the JVM.

      The MXBean query is expensive — on JDK 19+ each call reads /proc via Files.lines. So results are cached for CPU_LOAD_CACHE_MS. Callers such as the JobQueue pumper and the throttlers only need a coarse periodic sample, so up to 1s of staleness is acceptable.

      Returns:
      the CPU load
    • cpuLoadCacheStale

      static boolean cpuLoadCacheStale(long lastQueried, long now)
      Whether the cached CPU load sample is old enough to refresh. Never-queried (lastQueried == 0) counts as stale so the first call always queries the MXBean instead of returning the 0 initializer.
      Parameters:
      lastQueried - the wall-clock ms of the previous query, or 0
      now - the current wall-clock ms
      Returns:
      true if the cache should be refreshed
    • sysLoadCacheStale

      static boolean sysLoadCacheStale(long lastQueried, long now)
      Whether the cached system load sample is old enough to refresh. Never-queried (lastQueried == 0) counts as stale so the first call always queries the MXBean instead of returning the 0 initializer. A wall-clock step backwards (NTP correction, manual change) also counts as stale: a plain age comparison would report the sample as fresh until the clock caught up again, pinning a stale value for the length of the step.
      Parameters:
      lastQueried - the wall-clock ms of the previous query, or 0
      now - the current wall-clock ms
      Returns:
      true if the cache should be refreshed
    • getCPULoadAvg

      public static int getCPULoadAvg()
      Retrieve CPU Load Average of the JVM.
      Returns:
      the CPU load avg
    • getCPULoadCores

      public static double getCPULoadCores()
      60s-smoothed process CPU load expressed in cores, e.g. 2.3 on a 4-core machine means the JVM recently consumed 2.3 cores on average.
      Returns:
      the cores used, from 0.0 to getCores()
    • getSystemLoad

      public static int getSystemLoad()
      Retrieve the system load as a percentage, where 100% equals full system load.

      The MXBean query is a native /proc read and is cached for SYSTEM_LOAD_CACHE_MS, because this sits on the per-request path of both tunnel throttlers while the underlying load average moves on a multi-minute timescale.

      Returns:
      the system load
    • getActiveThreads

      public static int getActiveThreads()
      Returns the current number of active (live) threads in the JVM. This includes both daemon and non-daemon threads.
      Returns:
      the estimated number of active threads, or 0 if context or stat manager is unavailable
    • getTunnelBuildSuccess

      public static int getTunnelBuildSuccess()
      Retrieve Tunnel build success as a percentage.
      Returns:
      the tunnel build success
    • getTunnelBuildSuccessRatio

      public static double getTunnelBuildSuccessRatio(StatManager sm, int windowMs)
      The canonical tunnel build success ratio: successes over all settled builds, 0.0 to 1.0, for a stated window.

      This is the single source of truth. Three implementations existed and none of them agreed: ProfileOrganizer read getCurrentEventCount() - the current partial period - while asking for the ten minute rate, so it sampled a fraction of one bucket and threw the history away; the copy here read getLastEventCount(), the last completed period; and the Tuner used a different set of stats entirely on an hourly window. That value is not cosmetic - it gates profile eviction, selects the ghost cooldown, and feeds ClientPeerSelector first-hop selection - so a partial-period reading could intermittently drop it under the attack threshold and switch all three to their defensive behaviour on noise.

      Counts events over the last completed window rather than the current partial one, so the reading does not depend on where in the period it was sampled. Partial-period sampling was what made the old value swing, and swing under the attack threshold, which switches off profile eviction and lengthens ghost cooldowns.

      Parameters:
      sm - the stat manager, or null
      windowMs - the averaging window in milliseconds
      Returns:
      the ratio, or NaN if the stats are absent or the window is empty
    • buildSuccessRatio

      public static double buildSuccessRatio(double success, double reject, double expire)
      Successes over all settled builds. Pure arithmetic, so it is testable without stats.
      Parameters:
      success - mean successes per period
      reject - mean rejections per period
      expire - mean expiries per period
      Returns:
      the ratio, or NaN when nothing settled in the window