JDK-8339488 : Extended NPE message doesn't handle CONSTANT_Dynamic
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 24
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2024-09-03
  • Updated: 2024-09-16
  • Resolved: 2024-09-09
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 24
24 b15Fixed
Related Reports
Relates :  
Relates :  
Description
While running my application with a fastdebug build, I see an assertion failure:

```
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (<redacted>/src/hotspot/share/interpreter/bytecodeUtils.cpp:660), pid=12677, tid=12678
#  assert(false) failed: Unexpected tag
#
# JRE version: OpenJDK Runtime Environment 1.0.1973.0 (17.0.12+6) (fastdebug build 17.0.12+6-LTS)
# Java VM: OpenJDK 64-Bit Server VM 1.0.1973.0 (fastdebug 17.0.12+6-LTS, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0x73b2d8]  ExceptionMessageBuilder::do_instruction(int)+0x2858
```
with stack:
```
V  [libjvm.so+0x73b2d8]  ExceptionMessageBuilder::do_instruction(int)+0x2858
V  [libjvm.so+0x73b591]  ExceptionMessageBuilder::ExceptionMessageBuilder(Method*, int)+0x251
V  [libjvm.so+0x73de94]  BytecodeUtils::get_NPE_message_at(outputStream*, Method*, int)+0x134
V  [libjvm.so+0x10bf625]  JVM_GetExtendedNPEMessage+0x135
j  java.lang.NullPointerException.getExtendedNPEMessage()Ljava/lang/String;+0 java.base@17.0.12
j  java.lang.NullPointerException.getMessage()Ljava/lang/String;+23 java.base@17.0.12
```


It seems that https://github.com/openjdk/jdk/blob/master/src/hotspot/share/interpreter/bytecodeUtils.cpp#L646-L660 does not handle `CONSTANT_Dynamic` for the `ldc` instruction, even though https://openjdk.org/jeps/309 says:

> Dynamic constants must be usable in any context which currently allows general constant pool constants, such as CONSTANT_String and CONSTANT_MethodType. Thus, they must be valid operands to the ldc instruction and must be allowed as static parameters to bootstrap methods.

I'm not sure if there's a reason this is not permitted (my application uses Kotlin and Jacoco so there could be some unusual bytecode generated), or if it's just an omission. I see that `ConstantPool::constant_tag_at` looks like it would be suitable for finding the underlying type of the dynamic constant.
Comments
Changeset: 7c0f013d Branch: master Author: Oli Gillespie <ogillespie@openjdk.org> Date: 2024-09-09 14:53:36 +0000 URL: https://git.openjdk.org/jdk/commit/7c0f013d924a66c9cf55de761702b8de855e87fa
09-09-2024

A pull request was submitted for review. Branch: master URL: https://git.openjdk.org/jdk/pull/20889 Date: 2024-09-06 11:22:50 +0000
06-09-2024

Thanks for the reproducer [~ogillespie]! I haven't had a chance to look at this yet so you can take over if you have a fix.
05-09-2024

Attached a simple repro (updates CondyLDCTest to trigger this behaviour). I'll submit the fix tomorrow if you're not already on it, Matias
05-09-2024

Ah I see, sorry for the misunderstanding.
05-09-2024

[~dholmes], as Aleksey pointed out, the "Detailed NPE message feature" is analyzing *all* the beytcodes in a method up to the BCI where the NPE actually happened in order to find the root cause of the NPE and generate a better exception message. When CONSTANT_Dynamic was introduced, the bytecode parser for the "Detailed NPE message feature" has not been updated to handle the new constant. This doesn't mean that CONSTANT_Dynamic CP index itself or something related to the CONSTANT_Dynamic entry is null.
05-09-2024

"Simple omission" seems somewhat of an oversimplification. Looking at the definition of ldc: "Otherwise, the run-time constant pool entry is a symbolic reference to a method type, a method handle, or a dynamically computed constant. The symbolic reference is resolved (§5.4.3.5, §5.4.3.6) and value, the result of resolution, is pushed onto the operand stack." So if we have the index for a CONSTANT_Dynamic CP entry, what exactly could be null? Is there an error in the Constant_DYNAMIC entry itself? Do we hit NPE while resolving or executing the bootstrap method? Or is the result of the BSM itself null? Maybe all the Extended NPE code can do here is "do nothing" as it would in a release build?
04-09-2024

We looked at this with Oli. Crash in `JVM_GetExtendedNPEMessage` happens when we produce the NPE message somewhere, and while doing so we go and analyze the bytecode for <method,bci> where exception was raised. This analysis goes over the method bytecode from the beginning to the target BCI, which encounters ldc <condy> and fails. Looks like a simple omission in JDK-8218628. Oli is trying to get the simple reproducer done.
04-09-2024

I'll try to make a reproducer or extract the classfile. I just figured if it was an obvious miss in the handling then the specifics wouldn't be needed - should we handle CONSTANT_Dynamic for ldc in the extended npe message builder?
04-09-2024

Okay so maybe not a trivial miss then, let me try to extract the info, thanks for looking!
04-09-2024

[~ogillespie] can you provide a reproducer, or at least the classfile in question? You haven't show any actual details that this was a condy callsite, nor what exactly the NPE at that site means. Thanks
04-09-2024

I'm not sure how a NPE can arise in the context of a ldc with CONSTANT_Dynamic - what exactly is/could-be null?
04-09-2024