Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 50 additions & 3 deletions libs/jar-executor.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ module.exports = async function (deps) {
log.info(
`Launching client with ${memoryConfig.source} memory settings: ${memoryConfig.args.join(' ')}`
);
const commandArgs = [...memoryConfig.args, '-jar', jarPath];
const commandArgs = [...memoryConfig.args, ...GC_FLAGS, '-jar', jarPath];

Comment on lines +52 to 53
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's see the structure of the file and locate the key sections
wc -l libs/jar-executor.js

Repository: chsami/Microbot-Launcher

Length of output: 92


🏁 Script executed:

# Let's read the relevant sections: lines 52-53, 91-97, and the GC_FLAGS definition around 378-425
sed -n '45,100p' libs/jar-executor.js

Repository: chsami/Microbot-Launcher

Length of output: 2345


🏁 Script executed:

# Let's also check the preflight/version check logic around lines 145-186 and 338-374
sed -n '145,190p' libs/jar-executor.js

Repository: chsami/Microbot-Launcher

Length of output: 1628


🏁 Script executed:

# Read the GC_FLAGS definition area around lines 378-425
sed -n '370,430p' libs/jar-executor.js

Repository: chsami/Microbot-Launcher

Length of output: 2144


🏁 Script executed:

# Let's search for any Java version detection in the entire file
rg -n "version|Version|major|javaVersion|javaMajor" libs/jar-executor.js

Repository: chsami/Microbot-Launcher

Length of output: 1296


🌐 Web query:

ZGC garbage collector Java 14 15 when introduced production ready

💡 Result:

ZGC (Z Garbage Collector) was introduced experimentally in Java 11. It received significant improvements in Java 14, including Windows and macOS support, stability enhancements, and performance improvements. ZGC became production ready in Java 15 via JEP 377, which removed the experimental status and allowed enabling it simply with -XX:+UseZGC without unlocking experimental options.

Citations:


🌐 Web query:

-XX:IgnoreUnrecognizedVMOptions behavior prevent crash unrecognized flags Java

💡 Result:

Yes, -XX:+IgnoreUnrecognizedVMOptions prevents the JVM from crashing (exiting with "Error: Could not create the Java Virtual Machine") when it encounters unrecognized -XX VM options. By default (disabled), the JVM prints "Unrecognized VM option" and fails to start. When enabled, it ignores such options (and some improperly specified ones), allowing the JVM to start successfully. This option was added to HotSpot to facilitate testing across VM variants (server/client, product/debug) where flags differ (JDK-6788376). Examples: - Without: java -XX:+UseConcMarkSweepGC -version (on JDK15+) → "Unrecognized VM option 'UseConcMarkSweepGC' Error: Could not create the Java Virtual Machine." - With: java -XX:+IgnoreUnrecognizedVMOptions -XX:+UseConcMarkSweepGC -version → Starts successfully, ignoring the flag. Note: It may also ignore some invalid value errors (e.g., out-of-range), printing a warning but continuing (behavior noted in JDK-8129855 for JDK9+). Use cautiously as it can mask configuration errors. It's commonly used in IDEs/build tools for compatibility across JDK versions.

Citations:


🌐 Web query:

ZGC experimental Java 14 JDK 15 UseZGC UnlockExperimentalVMOptions

💡 Result:

In Java 14, ZGC is experimental and requires -XX:+UnlockExperimentalVMOptions -XX:+UseZGC to enable. In JDK 15, ZGC becomes production-ready via JEP 377, and -XX:+UnlockExperimentalVMOptions is no longer needed; use just -XX:+UseZGC.

Citations:


Add explicit Java version gating for ZGC flags, or remove the IgnoreUnrecognizedVMOptions fallback and require Java 15+.

ZGC is experimental in Java 14 (requires -XX:+UnlockExperimentalVMOptions) and production-ready from Java 15+ onward. The code appends -XX:+UseZGC unconditionally at lines 52–53 and 91–97 without checking the Java version. While -XX:+IgnoreUnrecognizedVMOptions prevents a JVM crash on Java 14, it causes silent degradation: the flag is ignored and the JVM falls back to G1GC. Since DEFAULT_XMX_VALUE was lowered to 600m assuming ZGC's behavior, Java 14 users would run with suboptimal settings. Either gate these flags on java -version output, or explicitly require Java 15+ and remove the IgnoreUnrecognizedVMOptions mitigation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/jar-executor.js` around lines 52 - 53, The code currently appends ZGC
flags unconditionally (see GC_FLAGS and the commandArgs spread that includes
GC_FLAGS) which can be ignored silently on Java <15; update libs/jar-executor.js
to detect the running Java major version (run and parse `java -version` output)
before building commandArgs and only include `-XX:+UseZGC`/related ZGC flags
when the parsed version is >=15; if version <15, do not add ZGC flags (and
remove the `-XX:+IgnoreUnrecognizedVMOptions` fallback) or alternatively fail
fast with a clear error requiring Java 15+; ensure any memory defaults like
DEFAULT_XMX_VALUE are consistent with the non-ZGC path when you skip adding ZGC
flags.

// apply proxy args (done differently depending on client version)
const err = addProxyArgs(commandArgs, proxy);
Expand Down Expand Up @@ -90,6 +90,7 @@ module.exports = async function (deps) {
);
const commandArgs = [
...memoryConfig.args,
...GC_FLAGS,
'-jar',
jarPath,
'-clean-jagex-launcher'
Expand Down Expand Up @@ -374,9 +375,55 @@ module.exports = async function (deps) {
};

const DEFAULT_XMS_VALUE = '512m';
const DEFAULT_XMX_VALUE = '1g';
const DEFAULT_XMX_VALUE = '600m'; // reduced from 1g — ZGC makes this safe to lower
const DEFAULT_CLIENT_RAM = DEFAULT_XMX_VALUE;
Comment on lines +378 to 379
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cat -n libs/jar-executor.js | sed -n '375,385p'

Repository: chsami/Microbot-Launcher

Length of output: 458


🏁 Script executed:

cat -n libs/jar-executor.js | sed -n '415,425p'

Repository: chsami/Microbot-Launcher

Length of output: 375


🏁 Script executed:

cat -n libs/jar-executor.js | wc -l

Repository: chsami/Microbot-Launcher

Length of output: 71


🏁 Script executed:

rg -n 'buildMemoryArgsFromRam' libs/jar-executor.js -A 20

Repository: chsami/Microbot-Launcher

Length of output: 2022


🏁 Script executed:

rg -n 'function\|const.*=.*=>' libs/jar-executor.js | grep -i memory

Repository: chsami/Microbot-Launcher

Length of output: 50


🏁 Script executed:

rg -n 'GC_FLAGS' libs/jar-executor.js -B 3 -A 3

Repository: chsami/Microbot-Launcher

Length of output: 935


🏁 Script executed:

rg -n 'args.*GC_FLAGS\|GC_FLAGS.*args\|concat\|spread' libs/jar-executor.js | head -20

Repository: chsami/Microbot-Launcher

Length of output: 50


Compute SoftMaxHeapSize from the actual memory configuration; the hardcoded value violates JVM constraints.

The hardcoded -XX:SoftMaxHeapSize=500m at line 419 is invalid with the default configuration: -Xms512m -Xmx600m -XX:SoftMaxHeapSize=500m places the soft max below the minimum heap size (500m < 512m), violating HotSpot's requirement that this flag stay between -Xms and -Xmx.

Additionally, buildMemoryArgsFromRam() (line 427) sets both -Xms and -Xmx to the same value for all RAM overrides, making SoftMaxHeapSize impossible to set validly in those cases. Derive the soft max from memoryConfig.args after memory configuration is finalized, and omit it entirely when -Xms === -Xmx.

This also applies to line 419.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/jar-executor.js` around lines 378 - 379, The current code hardcodes
-XX:SoftMaxHeapSize=500m which can violate JVM rules when DEFAULT_XMX_VALUE or
buildMemoryArgsFromRam produce -Xms/-Xmx ranges; update the logic so
SoftMaxHeapSize is computed from the finalized memoryConfig.args after
buildMemoryArgsFromRam runs: parse the effective -Xms and -Xmx values from
memoryConfig.args, only add -XX:SoftMaxHeapSize=<value> when Xms < Xmx and
choose a value between them (e.g. a percentage or Xmx minus a small delta), and
omit the SoftMaxHeapSize flag entirely when Xms === Xmx; ensure you change
usages tied to DEFAULT_XMX_VALUE and wherever -XX:SoftMaxHeapSize is currently
added (the hardcoded line and the section that applies memory overrides) so the
flag is derived from the final args rather than hardcoded.


/**
* GC flags injected into every client launch.
*
* -XX:+UseZGC
* Switch from G1GC to ZGC. G1GC holds committed heap pages indefinitely
* even when they contain only dead objects. ZGC is designed to return
* unused pages to the OS, so Task Manager reflects actual usage rather
* than the worst-case watermark.
*
* -XX:SoftMaxHeapSize=500m
* ZGC targets staying under 500 MB before expanding toward Xmx.
* Acts as a soft pressure valve — heap grows to 600m only under real load.
*
* -XX:+ZUncommit
* Enables ZGC's page uncommit feature. Without this flag ZGC still uses
* less memory than G1GC but won't actively shrink the committed footprint.
*
* -XX:ZUncommitDelay=30
* Pages idle for 30 seconds are returned to the OS. Lower values free
* memory faster; higher values reduce the cost of re-faulting pages back
* in after a brief spike.
*
* -XX:+UseStringDedup
* Deduplicates identical String objects across the heap. OSRS item names,
* NPC names, and chat messages frequently share the same content; this
* removes redundant copies automatically.
*
* -Xss512k
* Halves the per-thread stack from the default 1 MB. Microbot creates
* many script threads; 512 KB is ample for the call depths used.
*
* -XX:+IgnoreUnrecognizedVMOptions
* Prevents a crash if the bundled JRE is older than Java 15 and doesn't
* recognise ZGC flags — the client starts normally, just without the GC
* optimisations.
*/
const GC_FLAGS = [
'-XX:+UseZGC',
'-XX:SoftMaxHeapSize=500m',
'-XX:+ZUncommit',
'-XX:ZUncommitDelay=30',
'-XX:+UseStringDedup',
'-Xss512k',
'-XX:+IgnoreUnrecognizedVMOptions',
];

function buildMemoryArgsFromRam(ramValue, log, contextLabel) {
if (!ramValue || typeof ramValue !== 'string') {
return null;
Expand Down Expand Up @@ -431,4 +478,4 @@ function normalizeRamValue(value) {
const mb = unit === 'g' ? amount * 1024 : amount;

return { normalized: `${amount}${unit}`, mb };
}
}