Field Summary
FieldsModifier and TypeFieldDescriptionstatic final intDefault window forgetTunnelBuildSuccessRatio(StatManager, int).(package private) static final longMinimum interval between two OS queries for the process CPU load.static final StringThe account name a packaged Linux service runs the router under.static final booleanWith no override configured, slow platforms are still detected automatically.static final StringThe account name the Gentoo package runs the router service under, which differs from the one the other distributions use.static final StringSet to true to drop the single-core, low-memory term fromisSlow(), so a small router can still be treated as fast.(package private) static final longMinimum interval between two OS queries for the system load average.Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedThe host environment the router runs on, as reported by the OS and JVM properties probed below.Method Summary
All MethodsModifier and TypeMethodDescriptionstatic doublebuildSuccessRatio(double success, double reject, double expire) Successes over all settled builds.(package private) static booleancpuLoadCacheStale(long lastQueried, long now) Whether the cached CPU load sample is old enough to refresh.static intReturns the current number of active (live) threads in the JVM.static intIdentical toandroid.os.Build.VERSION.SDK_INT.static StringgetArch()Returns the architecture of the system running I2P as a string for reference inclients.configand plugin.config files.static intgetCores()Total CPUs including parked/offline cores.static intRetrieve CPU Load of the JVM.static intRetrieve CPU Load Average of the JVM.static double60s-smoothed process CPU load expressed in cores, e.g.static longRuntime.getRuntime().maxMemory()but check for bogus values.static StringgetOS()Returns the OS of the system running I2P as a lower-case string for reference inclients.configand plugin.config files.static intRetrieve the system load as a percentage, where 100% equals full system load.static TimeZoneThe system's time zone, which is probably different from the JVM time zone, because Router changes the JVM default to GMT.static TimeZoneThe system's time zone, which is probably different from the JVM time zone, because Router changes the JVM default to GMT.static intRetrieve Tunnel build success as a percentage.static doublegetTunnelBuildSuccessRatio(StatManager sm, int windowMs) The canonical tunnel build success ratio: successes over all settled builds, 0.0 to 1.0, for a stated window.static booleanIs the wrapper present? Same asI2PAppContext.hasWrapper().static booleanis64Bit()This isn't always correct.static booleanWhether the OS is Android.static booleanisApache()Apache Harmony JVM, or Android.static booleanisARM()Speed: do not cripple down for powerful ARM.static booleanisGentoo()True if Gentoo.static booleanisGNU()Gij or JamVM with GNU Classpath.static booleanisJava(int minVersion) Handles Android also.static booleanHandles Android, and minVersions in both forms (e.g.static booleanisJava10()True if the JVM is Java 10 or higher, false for Android.static booleanisJava11()True if the JVM is Java 11 or higher, false for Android.static booleanisJava12()True if the JVM is Java 12 or higher, false for Android.static booleanisJava13()True if the JVM is Java 13 or higher, false for Android.static booleanisJava14()True if the JVM is Java 14 or higher, false for Android.static booleanisJava15()True if the JVM is Java 15 or higher, false for Android.static booleanisJava16()True if the JVM is Java 16 or higher, false for Android.static booleanisJava17()True if the JVM is Java 17 or higher, false for Android.static booleanisJava18()True if the JVM is Java 18 or higher, false for Android.static booleanisJava19()True if the JVM is Java 19 or higher, false for Android.static booleanisJava20()True if the JVM is Java 20 or higher, false for Android.static booleanisJava21()True if the JVM is Java 21 or higher, false for Android.static booleanisJava22()True if the JVM is Java 22 or higher, false for Android.static booleanisJava6()Better than (new VersionComparator()).compare(System.getProperty(String)"java.version"), "1.6") >= 0 as it handles Android also, where java.version = "0".static booleanisJava7()Better than (new VersionComparator()).compare(System.getProperty(String)"java.version"), "1.7") >= 0 as it handles Android also, where java.version = "0".static booleanisJava8()True if the JVM is Java 8 or higher, false for Android.static booleanisJava9()True if the JVM is Java 9 or higher, false for Android.static booleanWhether running as a Linux service.static booleanisMac()Whether the OS is Mac.static booleanTrue if OpenJDK.static booleanWhether running as a service under either platform.static booleanisSlow()Our best guess on whether this is a slow architecture / OS / JVM, using some simple heuristics.static booleanWhether the OS is Windows.static booleanWhether running as a Windows service.static booleanisX86()True if x86.static booleanisZeroVM()Is this a very slow interpreted mode VM?static voidPrint the Java version and VM this router is running under, for diagnosing a user-reported problem from the console output.(package private) static booleansysLoadCacheStale(long lastQueried, long now) Whether the cached system load sample is old enough to refresh.static intCalculate how many (virtual) cores should be actually used by a thread pool.
Field Details
DAEMON_USER
The account name a packaged Linux service runs the router under.- See Also:
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_MSMinimum 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_MSMinimum 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
Set to true to drop the single-core, low-memory term fromisSlow(), 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_SLOWWith no override configured, slow platforms are still detected automatically.- See Also:
BUILD_SUCCESS_WINDOW_MS
public static final int BUILD_SUCCESS_WINDOW_MSDefault window forgetTunnelBuildSuccessRatio(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
Returns the OS of the system running I2P as a lower-case string for reference inclients.configand 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
Returns the architecture of the system running I2P as a string for reference inclients.configand 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
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.htmlsun.arch.data.modelnot on all JVMssun.arch.data.model== 64 => 64 bit processorsun.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 toandroid.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 asI2PAppContext.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 toRuntime.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
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 withDateFormat.setTimeZone().- Returns:
- non-null
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 withDateFormat.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
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 0now- 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 0now- 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
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:
ProfileOrganizerreadgetCurrentEventCount()- 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 readgetLastEventCount(), 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 feedsClientPeerSelectorfirst-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 nullwindowMs- 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 periodreject- mean rejections per periodexpire- mean expiries per period- Returns:
- the ratio, or NaN when nothing settled in the window