Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Native Image] MC server crashes when built with --pgo-instrument option: WaitForSingleObject failed with error 0x57 #10251

Open
2 tasks done
BlueGradientHorizon opened this issue Dec 6, 2024 · 3 comments
Assignees

Comments

@BlueGradientHorizon
Copy link

BlueGradientHorizon commented Dec 6, 2024

Describe the Issue

Native image tool is able to build a working executable of Minecraft server fork PaperMC if provided with enough metadata, but it crashes at runtime if built with --pgo-instrument command line option.

Using the latest version of GraalVM can resolve many issues.

GraalVM Version

java version "24" 2025-03-18
Java(TM) SE Runtime Environment Oracle GraalVM 24-dev+23.1 (build 24+23-jvmci-b01)
Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 24-dev+23.1 (build 24+23-jvmci-b01, mixed mode, sharing)

Oracle GraalVM for JDK 24 - early access build - 24.0.0-ea.22

Operating System and Version

Windows 11 23H2 22631.4317 amd64

Troubleshooting Confirmation

Run Command

See Steps to Reproduce section.

Expected Behavior

To be able to build an executable with --pgo-instrument and to run it without problems.

Actual Behavior

Runtime crash.

Steps to Reproduce

  1. I'm on Windows, and JFR isn't supported (source):

Note: JFR event recording is not yet available with Native Image on Windows.

But, interestingly, although I didn't enable it via passing cmd arguments to native-image, mc server was crashing.

Stacktrace
[18:27:55] [main/WARN]: Failed to load datapacks, can't proceed with server load. You can either fix your datapacks or reset to vanilla with --safeMode
java.util.concurrent.ExecutionException: java.lang.UnsatisfiedLinkError: jdk.jfr.internal.JVM.isExcluded(Ljava/lang/Class;)Z [symbol: Java_jdk_jfr_internal_JVM_isExcluded or Java_jdk_jfr_internal_JVM_isExcluded__Ljava_lang_Class_2]
	at java.base/java.util.concurrent.CompletableFuture.wrapInExecutionException(CompletableFuture.java:347) ~[org.bukkit.craftbukkit.main.exe:?]
	at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:442) ~[org.bukkit.craftbukkit.main.exe:?]
	at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2119) ~[org.bukkit.craftbukkit.main.exe:?]
	at net.minecraft.server.Main.main(Main.java:304) ~[?:?]
	at io.papermc.paper.PaperBootstrap.boot(PaperBootstrap.java:21) ~[?:?]
	at org.bukkit.craftbukkit.Main.main(Main.java:281) ~[?:?]
	at java.base/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH) ~[?:?]
Caused by: java.lang.UnsatisfiedLinkError: jdk.jfr.internal.JVM.isExcluded(Ljava/lang/Class;)Z [symbol: Java_jdk_jfr_internal_JVM_isExcluded or Java_jdk_jfr_internal_JVM_isExcluded__Ljava_lang_Class_2]
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.jni.access.JNINativeLinkage.getOrFindEntryPoint(JNINativeLinkage.java:152) ~[?:?]
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.jni.JNIGeneratedMethodSupport.nativeCallAddress(JNIGeneratedMethodSupport.java:41) ~[?:?]
	at jdk.jfr@24/jdk.jfr.internal.JVM.isExcluded(Native Method) ~[?:?]
	at jdk.jfr@24/jdk.jfr.internal.MetadataRepository.register(MetadataRepository.java:139) ~[?:?]
	at jdk.jfr@24/jdk.jfr.internal.MetadataRepository.register(MetadataRepository.java:134) ~[?:?]
	at jdk.jfr@24/jdk.jfr.FlightRecorder.register(FlightRecorder.java:129) ~[org.bukkit.craftbukkit.main.exe:?]
	at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[org.bukkit.craftbukkit.main.exe:?]
	at net.minecraft.util.profiling.jfr.JfrProfiler.<init>(JfrProfiler.java:79) ~[?:?]
	at net.minecraft.util.profiling.jfr.JfrProfiler.<clinit>(JfrProfiler.java:79) ~[?:?]
	at net.minecraft.util.profiling.jfr.JvmProfiler.<clinit>(JvmProfiler.java:49) ~[org.bukkit.craftbukkit.main.exe:1.21.3-80-c2294d7]
	at net.minecraft.commands.Commands.<init>(Commands.java:225) ~[org.bukkit.craftbukkit.main.exe:1.21.3-80-c2294d7]
	at net.minecraft.server.ReloadableServerResources.<init>(ReloadableServerResources.java:41) ~[?:?]
	at net.minecraft.server.ReloadableServerResources.lambda$loadResources$1(ReloadableServerResources.java:85) ~[?:?]
	at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1196) ~[?:?]
	at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:556) ~[org.bukkit.craftbukkit.main.exe:?]
	at java.base/java.util.concurrent.CompletableFuture.postFire(CompletableFuture.java:660) ~[org.bukkit.craftbukkit.main.exe:?]
	at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:699) ~[?:?]
	at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:528) ~[org.bukkit.craftbukkit.main.exe:?]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[org.bukkit.craftbukkit.main.exe:?]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?]
	at java.base/java.lang.Thread.runWith(Thread.java:1589) ~[org.bukkit.craftbukkit.main.exe:?]
	at java.base/java.lang.Thread.run(Thread.java:1576) ~[org.bukkit.craftbukkit.main.exe:?]
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:832) [org.bukkit.craftbukkit.main.exe:?]
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:808) [org.bukkit.craftbukkit.main.exe:?]

Later I've checked how native executable will behave if compiled for linux aarch64 (Termux, ubuntu proot-distro) using the same GraalVM EA version, but I got the same exception message. Anyway I solved this problem by creating a patch for PaperMC and compiling it from source.

  1. Run the server bootstrapper for the first time to unpack libraries and patch official server with Paper patches
java -jar paper-paperclip-1.21.3-R0.1-SNAPSHOT-mojmap.jar
  1. Execute powershell script to generate args.txt file containing classpath argument and main class name
$libs = (ls .\libraries\ -Recurse -Include *.jar | % { $_.FullName }) -Split([Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries) -join ";"
$content = -join("-cp versions\1.21.3\paper-1.21.3.jar;", $libs, " org.bukkit.craftbukkit.Main")
[IO.File]::WriteAllLines("args.txt", $content)
  1. Run the server with metadata tracing agent
java -agentlib:native-image-agent=config-merge-dir=./,config-write-period-secs=10 @args.txt nogui

First, you'll need to accept Minecraft EULA. Edit eula.txt and set eula value to true and then run the server again using the same command.
Based on experience gained previously, it is indeed necessary to log into the server using the Minecraft client and perform some actions (generating chunks, joining other worlds, etc.), otherwise you will receive a file with incomplete metadata and will not be able to log into the server compiled to native executable.
You can download my example of working reachablity_metadata.json for Windows - link.

  1. Slightly modify reachability-metadata.json
    By some reason, native image agent does not include all files of the data directory inside server jar into that file, but these are crucial for server to run, so replace:
    {
      "glob": "data/.mcassetsroot"
    },

with

    {
      "glob": "data/**"
    },
  1. Build and run native image without --pgo-instrument option
native-image --no-fallback --enable-url-protocols=http,https --initialize-at-build-time=net.minecraft.util.profiling.jfr.event,org.apache.logging.log4j,net.minecrell.terminalconsole.TCALookup -H:+UnlockExperimentalVMOptions -H:ConfigurationFileDirectories=./ -H:+AddAllCharsets -H:+IncludeAllLocales @args.txt
org.bukkit.craftbukkit.main.exe nogui

nogui is mandatory or you'll get java.lang.NoSuchMethodError: java.awt.Toolkit.getDefaultToolkit()Ljava/awt/Toolkit; (by default it will try to open GUI window with console and memory monitor). Server should start up without problems.

  1. Build and run native image with --pgo-instrument option
native-image ... --pgo-instrument @args.txt

Server will crash shortly after starting, at least on Windows.

Additional Context

Zip archive with:

  • scripts I was using
  • PaperMC bootstrapper with my patch
  • examples of native images compiled with and without --pgo-instrument for Windows (ni-pgo-instrument and ni-normal directories respectively)
  • native image bundle (in ni-normal directory)
  • correct reachability-metadata.json for Windows

link.

If by some reason you can't to download zip files, you can download files from my repo.

Run-Time Log Output and Error Messages

[15:18:25 INFO]: [bootstrap] Running Java 24 (Substrate VM 24+23; Oracle Corporation Oracle GraalVM 24-dev+23.1) on Windows 11 10.0 (amd64)
[15:18:25 INFO]: [bootstrap] Loading Paper 1.21.3-DEV (2024-12-06T12:18:25Z) for Minecraft 1.21.3
[15:18:26 INFO]: [PluginInitializerManager] Initializing plugins...
[15:18:26 INFO]: [PluginInitializerManager] Initialized 0 plugins
WaitForSingleObject failed with error 0x57
@BlueGradientHorizon
Copy link
Author

Retested with

java version "24" 2025-03-18
Java(TM) SE Runtime Environment Oracle GraalVM 24-dev+24.1 (build 24+24-jvmci-b01)
Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 24-dev+24.1 (build 24+24-jvmci-b01, mixed mode, sharing)

No changes in behaviour.

@selhagani selhagani self-assigned this Dec 9, 2024
@selhagani
Copy link
Member

Hi @BlueGradientHorizon,

Thank you for reaching out to us!

I am attempting to reproduce the issue you encountered, but when I try to apply the patch you provided, I encounter the following error:
error: src/main/java/net/minecraft/util/profiling/jfr/JvmProfiler.java: No such file or directory

I’m unsure why this is happening. Would you have any insights on how I might resolve this?

Additionally, if possible, could you create a more concise reproducer to specifically target this issue? If that’s not feasible, could you try adding the following option to your native image build: --verbose? This should provide more detailed error output, which could help us identify the root cause.

@BlueGradientHorizon
Copy link
Author

BlueGradientHorizon commented Dec 9, 2024

Hello!

I am attempting to reproduce the issue you encountered, but when I try to apply the patch you provided, I encounter the following error: error: src/main/java/net/minecraft/util/profiling/jfr/JvmProfiler.java: No such file or directory

To properly apply the patch and compile server, you need to do following:

  1. Clone PaperMC repo.
  2. Download my patch file and place it into patches\server directory.
  3. gradlew.bat applyPatches
  4. gradlew.bat createMojmapPaperclipJar

You're getting this error because Paper-Server directory (and also Paper-API) contain only files which are modified by patches and all other unmodified files are located in Paper-Server\.gradle\caches\paperweight\mc-dev-sources. There were no patches previously which modify JvmProfiler.java file. Paper and other Minecraft server forks projects have very tricky building system and use uncommon techniques of developing (see contributing guidelines).

Additionally, if possible, could you create a more concise reproducer to specifically target this issue?

Unfortunately, I'm not able to write up a simpler reproducer, sorry.

If that’s not feasible, could you try adding the following option to your native image build: --verbose? This should provide more detailed error output, which could help us identify the root cause.

Ok, I'll try.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants