From ee53911a06c79617b5c5d7b0b36910350ffb0deb Mon Sep 17 00:00:00 2001 From: sanasol Date: Fri, 27 Feb 2026 23:15:01 +0100 Subject: [PATCH] Revert debug builds, update fastutil issue docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent and -Xshare:off both ruled out as causes. Restored normal agent injection. Updated docs with complete findings — issue remains unsolved. Co-Authored-By: Claude Opus 4.6 --- backend/managers/gameLauncher.js | 10 ++- docs/FASTUTIL_CLASSLOADER_ISSUE.md | 118 +++++++++-------------------- 2 files changed, 44 insertions(+), 84 deletions(-) diff --git a/backend/managers/gameLauncher.js b/backend/managers/gameLauncher.js index 16a789f..39c5e32 100644 --- a/backend/managers/gameLauncher.js +++ b/backend/managers/gameLauncher.js @@ -482,11 +482,15 @@ async function launchGame(playerNameOverride = null, progressCallback, javaPathO } } - // DualAuth Agent: DISABLED for debug - testing fastutil classloader issue - // TODO: re-enable after testing + // DualAuth Agent: Set JAVA_TOOL_OPTIONS so java picks up -javaagent: flag + // This enables runtime auth patching without modifying the server JAR const agentJar = path.join(gameLatest, 'Server', 'dualauth-agent.jar'); if (fs.existsSync(agentJar)) { - console.log('DualAuth Agent: SKIPPED (debug build - fastutil classloader test)'); + const agentFlag = `-javaagent:"${agentJar}"`; + env.JAVA_TOOL_OPTIONS = env.JAVA_TOOL_OPTIONS + ? `${env.JAVA_TOOL_OPTIONS} ${agentFlag}` + : agentFlag; + console.log('DualAuth Agent: enabled via JAVA_TOOL_OPTIONS'); } try { diff --git a/docs/FASTUTIL_CLASSLOADER_ISSUE.md b/docs/FASTUTIL_CLASSLOADER_ISSUE.md index 2b818e2..65de1ed 100644 --- a/docs/FASTUTIL_CLASSLOADER_ISSUE.md +++ b/docs/FASTUTIL_CLASSLOADER_ISSUE.md @@ -1,10 +1,10 @@ # Singleplayer Server Crash: fastutil ClassNotFoundException -## Status: Open (multiple users, Feb 24-27 2026) +## Status: Open — NO SOLUTION (Feb 24-27 2026) ## Symptom -Singleplayer server crashes immediately after DualAuth Agent installs successfully: +Singleplayer server crashes immediately on boot: ``` Exception in thread "main" java.lang.NoClassDefFoundError: it/unimi/dsi/fastutil/objects/ObjectArrayList @@ -25,99 +25,55 @@ Server exits with code 1. Multiplayer works fine for the same user. - Multiplayer works fine for both users - macOS/Linux users are NOT affected -## What Works +## Ruled Out (confirmed via debug builds) -- Java wrapper correctly strips `-XX:+UseCompactObjectHeaders` -- Java wrapper correctly injects `--disable-sentry` -- DualAuth Agent v1.1.12 installs successfully (STATIC mode) -- Multiplayer connections work fine -- Repair and reinstall did NOT fix the issue +| Suspect | Tested | Result | +|---------|--------|--------| +| **DualAuth Agent** | Debug build with agent completely disabled (`debug-no-agent` tag) | **Same crash.** Agent is innocent. | +| **`-Xshare:off` (CDS)** | Added to `JAVA_TOOL_OPTIONS` in launcher code (`debug-xshare-off` tag) | **Did not help.** CDS is not the cause. | +| **`-XX:+UseCompactObjectHeaders`** | Stripped via wrapper | **Did not help.** Server has `-XX:+IgnoreUnrecognizedVMOptions` anyway. | +| **Corrupted game files** | User did repair + full reinstall | **Same crash.** | +| **Java wrapper** | Logs confirm wrapper works correctly | Not the cause. | +| **ARM64/Parallels** | User is on standard Windows x86_64 | Not applicable. | +| **AOT cache** | Asentrix has no AOT errors (JAYED did), both crash the same way | Not the root cause. | -## Root Cause Analysis +## What We Know -`fastutil` (`it.unimi.dsi.fastutil`) should be bundled inside `HytaleServer.jar` (fat JAR). The `ClassNotFoundException` means the JVM's app classloader cannot find it despite it being in the JAR. +- `fastutil` is bundled inside `HytaleServer.jar` (fat/shaded JAR) — same JAR for all users +- JVM's `BuiltinClassLoader` cannot find `it.unimi.dsi.fastutil.objects.ObjectArrayList` despite it being in the JAR +- Crash happens at `EarlyPluginLoader` static initializer (line 34) which imports `ObjectArrayList` +- The bundled JRE is identical for all users (downloaded by launcher) +- The issue is **not** caused by anything the F2P launcher adds — it's the vanilla server JVM failing to load its own classes -### Ruled Out +## Remaining Theories -- **Wrapper issue**: Wrapper is working correctly (confirmed in logs) -- **UseCompactObjectHeaders**: Server also has `-XX:+IgnoreUnrecognizedVMOptions`, so unrecognized flags don't crash it -- **DualAuth Agent**: Works for all other users; agent installs successfully before the crash -- **Corrupted game files**: Repair/reinstall didn't help -- **ARM64/Parallels**: User is on standard Windows, not ARM +1. **Antivirus/security software** — Windows Defender or third-party AV intercepting JAR file reads. Real-time scanning + fat JAR = known conflict. **Untested** — user should try disabling AV temporarily. +2. **Windows Insider build** — Asentrix is on NT 10.0.26200.0 (Windows 11 Dev/Insider). Bleeding-edge Windows may have JVM compatibility issues. +3. **File locking** — Stalled `java.exe` processes holding `HytaleServer.jar` open (Asentrix had stalled processes killed at every launch). +4. **Corrupted JRE on disk** — Despite being the same download, filesystem or AV may have corrupted specific JRE files on their system. -### Likely Cause +## Next Steps to Try -**CDS (Class Data Sharing) broken by bootstrap classloader modification.** DualAuth agent calls `appendToBootstrapClassLoaderSearch()` which triggers JVM warning: `"Sharing is only supported for boot loader classes because bootstrap classpath has been appended"`. This disables AppCDS for application classes. On some Windows systems, this breaks the classloader's ability to find classes (including fastutil) from the fat JAR. - -This warning appears for ALL users, but only breaks classloading on some Windows systems — reason unknown. - -### Other Possible Causes - -1. **Antivirus interference** — AV blocking Java from reading classes out of JAR files -2. **File locking** — another process holding HytaleServer.jar open (Asentrix had stalled java.exe killed at launch) - -## Potential Fix: `-Xshare:off` (testing Feb 27) - -Disables CDS entirely, forcing standard classloading. User can add via launcher: -1. **Settings** → **Java Wrapper Configuration** → **Arguments to Inject** -2. Add `-Xshare:off` with **Server Only** condition -3. Retry singleplayer - -Sent to affected users for testing — **awaiting results**. - -If confirmed, should be added as default inject arg (server-only) in launcher config. - -## Debugging Steps (for reference) - -Most steps are impractical for F2P users: -- ~~Official Hytale singleplayer~~ — F2P users don't have official access -- ~~Try without DualAuth agent~~ — not possible, agent required for F2P token validation -- ~~Verify fastutil in JAR~~ — same JAR for all users, not a user-actionable step -- ~~Check JRE version~~ — bundled with launcher, same for all users - -**Practical steps:** -1. **Add `-Xshare:off`** via wrapper inject args (server-only) — testing now -2. **Check antivirus** — add game directory to Windows Defender exclusions -3. **Check for stalled processes** — kill any leftover java.exe/HytaleServer before launch +1. **Disable Windows Defender** temporarily — the only quick test left +2. **Delete bundled JRE** and let launcher re-download — rules out local JRE corruption +3. **Ask if official Hytale singleplayer works** — if it also crashes, it's their system (but F2P users may not have access) ## Update History -### Feb 24: `-XX:+UseCompactObjectHeaders` stripping removed from defaults -Stripping this flag did NOT fix the issue. The server already has `-XX:+IgnoreUnrecognizedVMOptions` so unrecognized flags are harmless. The flag was removed from default `stripFlags` in `backend/core/config.js`. +### Feb 24: First report (JAYED) +User reported singleplayer crash. Initial investigation found AOT cache errors + fastutil ClassNotFoundException. Stripping `-XX:+UseCompactObjectHeaders` did not help. -### Feb 27: Second user (Asentrix) reported, `-Xshare:off` sent for testing -Asentrix hit the same crash on Launcher v2.4.4. Unlike JAYED, no AOT cache errors — just the CDS sharing warning followed by fastutil ClassNotFoundException. This confirms the issue is not AOT-specific but related to CDS/classloader interaction with the DualAuth agent's bootstrap CL modification. Sent `-Xshare:off` workaround to affected users — awaiting results. - -## Using the Java Wrapper to Strip JVM Flags - -If a user needs to strip a specific JVM flag (e.g., for debugging or compatibility), they can do it via the launcher UI: - -1. Open **Settings** → scroll to **Java Wrapper Configuration** -2. Under **JVM Flags to Remove**, type the flag (e.g. `-XX:+UseCompactObjectHeaders`) and click **Add** -3. The flag will be stripped from all JVM invocations at launch time -4. To inject custom arguments, use the **Arguments to Inject** section (with optional "Server Only" condition) -5. **Restore Defaults** resets to empty strip flags + `--disable-sentry` (server only) - -The wrapper generates platform-specific scripts at launch time: -- **Windows**: `java-wrapper.bat` in `jre/latest/bin/` -- **macOS/Linux**: `java-wrapper` shell script in the same directory - -Config is stored in `config.json` under `javaWrapperConfig`: -```json -{ - "javaWrapperConfig": { - "stripFlags": ["-XX:+SomeFlag"], - "injectArgs": [ - { "arg": "--some-arg", "condition": "server" }, - { "arg": "--other-arg", "condition": "always" } - ] - } -} -``` +### Feb 27: Second report (Asentrix), extensive debugging +- Asentrix hit same crash, no AOT errors — ruled out AOT as root cause +- Built `debug-xshare-off`: added `-Xshare:off` to `JAVA_TOOL_OPTIONS` — **did not help** +- Built `debug-no-agent`: completely disabled DualAuth agent — **same crash** +- **Conclusion**: Neither the agent nor CDS is the cause. The JVM itself cannot load classes from the fat JAR on these specific Windows systems. +- Note: wrapper `injectArgs` append AFTER `-jar`, so they cannot inject JVM flags — only `JAVA_TOOL_OPTIONS` works for JVM flags ## Related - Java wrapper config: `backend/core/config.js` (stripFlags / injectArgs) - DualAuth Agent: v1.1.12, package `ws.sanasol.dualauth` - Game version at time of reports: `2026.02.19-1a311a592` -- Log submission ID (Asentrix): `c88e7b71` +- Debug tags: `debug-xshare-off`, `debug-no-agent` +- Log submission IDs: `c88e7b71` (Asentrix initial), `0445e4dc` (xshare test), `748dceeb` (no-agent test)