JDK-8329126 : No native wrappers generated anymore with -XX:-TieredCompilation after JDK-8251462
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 17,21,23
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2024-03-26
  • Updated: 2024-06-28
  • Resolved: 2024-03-30
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 17 JDK 21 JDK 23
17.0.13-oracleFixed 21.0.5-oracleFixed 23 b17Fixed
Related Reports
Relates :  
Relates :  
Description
Since [JDK-8251462: Simplify compilation policy](https://bugs.openjdk.org/browse/JDK-8251462), introduced in JDK 17, no native wrappers are generated any more if running with `-XX:-TieredCompilation` (i.e. native methods are not compiled any more).

The attached JMH benchmark demonstrate that native method calls became twice as expensive with JDK 17:
```
  public static native void emptyStaticNativeMethod();

  @Benchmark
  public static void baseline() {
  }

  @Benchmark
  public static void staticMethodCallingStatic() {
    emptyStaticMethod();
  }

  @Benchmark
  public static void staticMethodCallingStaticNative() {
    emptyStaticNativeMethod();
  }

  @Benchmark
  @Fork(jvmArgsAppend = "-XX:-TieredCompilation")
  public static void staticMethodCallingStaticNativeNoTiered() {
    emptyStaticNativeMethod();
  }

  @Benchmark
  @Fork(jvmArgsAppend = "-XX:+PreferInterpreterNativeStubs")
  public static void staticMethodCallingStaticNativeIntStub() {
    emptyStaticNativeMethod();
  }
```

JDK 11
======
```
Benchmark                                           Mode  Cnt   Score   Error  Units
NativeCall.baseline                                 avgt    5   0.390 ± 0.016  ns/op
NativeCall.staticMethodCallingStatic                avgt    5   1.693 ± 0.053  ns/op
NativeCall.staticMethodCallingStaticNative          avgt    5  10.287 ± 0.754  ns/op
NativeCall.staticMethodCallingStaticNativeNoTiered  avgt    5   9.966 ± 0.248  ns/op
NativeCall.staticMethodCallingStaticNativeIntStub   avgt    5  20.384 ± 0.444  ns/op
```

JDK 17 & 21
===========
```
Benchmark                                           Mode  Cnt   Score   Error  Units
NativeCall.baseline                                 avgt    5   0.390 ± 0.017  ns/op
NativeCall.staticMethodCallingStatic                avgt    5   1.852 ± 0.272  ns/op
NativeCall.staticMethodCallingStaticNative          avgt    5  10.648 ± 0.661  ns/op
NativeCall.staticMethodCallingStaticNativeNoTiered  avgt    5  20.657 ± 1.084  ns/op
NativeCall.staticMethodCallingStaticNativeIntStub   avgt    5  22.429 ± 0.991  ns/op
```

The issue can bee seen if we run with `-XX:+PrintCompilation -XX:+PrintInlining`. With JDK 11 we get the following output for `-XX:+TieredCompilation`:
```
    172  111    b  3       io.simonis.NativeCall::staticMethodCallingStaticNative (4 bytes)
                              @ 0   io.simonis.NativeCall::emptyStaticNativeMethod (0 bytes)   native method
    172  112     n 0       io.simonis.NativeCall::emptyStaticNativeMethod (native)   (static)
    173  113    b  4       io.simonis.NativeCall::staticMethodCallingStaticNative (4 bytes)
                              @ 0   io.simonis.NativeCall::emptyStaticNativeMethod (0 bytes)   native method
    173  111       3       io.simonis.NativeCall::staticMethodCallingStaticNative (4 bytes)   made not entrant
```
As you can see, the native wrapper for `NativeCall::emptyStaticNativeMethod()` gets compiled with compiled id 112. If we run with `-XX:-TieredCompilation`:
```
    117    5    b        io.simonis.NativeCall::staticMethodCallingStaticNative (4 bytes)
                            @ 0   io.simonis.NativeCall::emptyStaticNativeMethod (0 bytes)   native method
    117    6     n       io.simonis.NativeCall::emptyStaticNativeMethod (native)   (static)
```
There's still a native wrapper created with compile id 6.

With JDK 17 and later, the `-XX:+PrintCompilation` output looks similar for the default `-XX:+TieredCompilation` case:
```
     56   26    b  3       io.simonis.NativeCall::staticMethodCallingStaticNative (4 bytes)
                              @ 0   io.simonis.NativeCall::emptyStaticNativeMethod (0 bytes)   native method
     56   27     n 0       io.simonis.NativeCall::emptyStaticNativeMethod (native)   (static)
     56   28    b  4       io.simonis.NativeCall::staticMethodCallingStaticNative (4 bytes)
                              @ 0   io.simonis.NativeCall::emptyStaticNativeMethod (0 bytes)   native method
     56   26       3       io.simonis.NativeCall::staticMethodCallingStaticNative (4 bytes)   made not entrant
```
But with `-XX:-TieredCompilation`, we don't generate the native wrapper any more:
```
     58    5    b        io.simonis.NativeCall::staticMethodCallingStaticNative (4 bytes)
                            @ 0   io.simonis.NativeCall::emptyStaticNativeMethod (0 bytes)   native method

```
Which basically means that we're always invoking the native method through the interpreter stub.

Comments
[jdk17u-fix-request] Approval Request from Martin Should get backported for parity with 17.0.12-oracle. Applies cleanly. Tier 1-4 have passed.
04-06-2024

A pull request was submitted for review. URL: https://git.openjdk.org/jdk17u-dev/pull/2529 Date: 2024-06-03 21:02:26 +0000
03-06-2024

[jdk21u-fix-request] Approval Request from Martin Should get backported for parity with 21.0.5-oracle. Applies cleanly and tier 1-4 have passed.
01-06-2024

A pull request was submitted for review. URL: https://git.openjdk.org/jdk21u-dev/pull/635 Date: 2024-05-31 15:49:36 +0000
31-05-2024

Notice that because Critical JNI Natives are only available from the compiled native wrappers, this bug basically disables Critical JNI Natives (i.e. `-XX:+CriticalJNINatives`) when running with `-XX:-TieredCompilation` in JDK 17. Critical JNI Natives have been removed in JDK 18.
07-04-2024

Changeset: f2e5808b Author: Volker Simonis <simonis@openjdk.org> Date: 2024-03-30 12:47:51 +0000 URL: https://git.openjdk.org/jdk/commit/f2e5808b46a3da6920dd56688c877ee0e2795de6
30-03-2024

Good catch, [~simonis]! ILW = Performance regression for native calls, with -XX:-TieredCompilation, no workaround but enable TieredCompilation = MMH = P3
27-03-2024

A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/18496 Date: 2024-03-26 19:14:23 +0000
26-03-2024