Skip to content

Inconsistent Behavior Between OpenJ9 and Hotspot in java.lang.Runtime.getRuntime().addShutdownHook #21906

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

Open
Xniao opened this issue May 19, 2025 · 4 comments

Comments

@Xniao
Copy link

Xniao commented May 19, 2025

Java -version output

Hotspot

java 21.0.7 2025-04-15 LTS
Java(TM) SE Runtime Environment (build 21.0.7+8-LTS-245)
Java HotSpot(TM) 64-Bit Server VM (build 21.0.7+8-LTS-245, mixed mode, sharing)

OpenJ9

openjdk 21.0.7 2025-04-15 LTS
IBM Semeru Runtime Open Edition 21.0.7.0 (build 21.0.7+6-LTS)
Eclipse OpenJ9 VM 21.0.7.0 (build openj9-0.51.0, JRE 21 Linux amd64-64-Bit Compressed References 20250415_458 (JIT enabled, AOT enabled)
OpenJ9   - 31cf5538b0
OMR      - 9bcff94a2
JCL      - 26c2dc3d801 based on jdk-21.0.7+6)

OS

wsl2-ubuntu 22.04
Linux 5.15.167.4-microsoft-standard-WSL2 #1 SMP Tue Nov 5 00:21:55 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

Summary of problem

When compiling and running the test case below with JDK21 using Hotspot and OpenJ9, the program behaves differently.

  • When using Hotspot, the program executes successfully.
  • When using OpenJ9, the program will throw java.lang.IllegalStateException.

Reproduce Steps

  1. Source code of Test.java
public class Test {

    public static void main(String[] strArr) {
        try {
            int count = 1;
            do {
                long timeoutMs = 1000L;
                java.util.Timer timer = new java.util.Timer(true);
                timer.schedule(new java.util.TimerTask() {

                    @Override
                    public void run() {
                        java.lang.System.exit(0);
                    }
                }, timeoutMs);
                java.lang.Runtime.getRuntime().addShutdownHook(new java.lang.Thread(() -> {
                    long startTime = java.lang.System.currentTimeMillis();
                }));
                int threadCount = 10;
                int listSize = 100000;
                for (int i = 0; i < threadCount; i++) {
                    new java.lang.Thread(() -> {
                        for (int j = 0; j < listSize; j++) {
                            java.util.LinkedList<Object> list = new java.util.LinkedList<>();
                            list.add(new Object());
                        }
                    }).start();
                }
            } while (++count < 282);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
  1. Compile the program with command
javac Test.java
  1. Run the program using Hotspot. Nothing happens.
path/to/hotspot/bin/java Test
  1. Run the program using OpenJ9. The program will throw java.lang.IllegalStateException.
path/to/openj9/bin/java Test
java.lang.IllegalStateException: Shutdown in progress
        at java.base/java.lang.ApplicationShutdownHooks.add(ApplicationShutdownHooks.java:67)
        at java.base/java.lang.Runtime.addShutdownHook(Runtime.java:250)
        at Test.main(Test.java:16)

Here are the source file and corresponding class file.

testcase.zip

@pshipton
Copy link
Member

@hzongaro seems like a JIT issue.
Hotspot is able to run all the operations in less than 1 sec (real 0m0.652s), but OpenJ9 usually cannot so the IllegalStateException occurs.

@keithc-ca
Copy link
Contributor

Do you really want to add multiple shutdown hooks? If not, the call should be before the loop. Either way,it should be before scheduling the task that will call System.exit().

@pshipton
Copy link
Member

I don't think that is the point. The user is looking for incorrect behavior of OpenJ9 compared to Hotspot.

@keithc-ca
Copy link
Contributor

I think it is the point: depending on how long it takes to get from the (first) schedule() call to the check within each addShutdownHook() call is the fundamental issue with the sample code. Reorder those calls, and that timing is no longer an issue.

To clarify, the loop just makes it worse; increase the limit to something higher than 282 and Hotspot will also fail.

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

3 participants