premain: Crash in Infinispan server code caused by NPE under MethodHandleNative::linkDynamicConstant
Andrew Dinn
adinn at redhat.com
Wed Sep 11 09:39:20 UTC 2024
[n.b. resent using correct email id]
A crash due to an NPE was observed in the Infinispan (Data Grid) server
app when deployed using the Leyden EA. The crash still manifests with
the latest premain code. The crash happens when an application call
which employs a method reference as argument enters
MethodHandleNative::linkDynamicConstant().
putMakedPasswordImplementations(this::putService, this);
Debugging shows that the call to linkDynamicConstant() returns null.
A simple reproducer for the problem is available as a maven project on
github:
https://github.com/tristantarrant/elytron-leyden
The ReadMe provides an explanation of how to reproduce the problem. I
did so and the debugged to find out some of the details of what is
happening (see below) but did not fully clarify the problem. Help from
someone more conversant with the ins and outs of method handle
bootstraps in premain would be welcome. Details follow.
regards,
Andrew Dinn
-----------
I downloaded the git repo and attached the Java sources using Maven command
$ mvn dependency:sources
Having manifested the crash by following the instructions in the README
I reran the leyden JVM under gdb using the following commands to enable
Java debugging
$ gdb ${LEYDEN_HOME}/bin/java
(gdb) cd /path/to/mvn/project
(gdb) run
-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005
-classpath
/home/adinn/redhat/openjdk/infinispan/elytron-leyden/base/target/elytron-leyden-base-0.0.1-SNAPSHOT.jar:/home/adinn/.m2/repository/org/wildfly/security/wildfly-elytron-credential/2.5.1.Final/wildfly-elytron-credential-2.5.1.Final.jar:/home/adinn/.m2/repository/org/wildfly/security/wildfly-elytron-base/2.5.1.Final/wildfly-elytron-base-2.5.1.Final.jar
-XX:CacheDataStore=elytron.aot com.redhat.leyden.Main
The problem manifests at WildflyElytronBaseProvider.java:107 in method
WildflyElytronBaseProvider::putPasswordImplementations() at a call to
method putMakedPasswordImplementations:
. . .
putService(new Service(this, PASSWORD_FACTORY_TYPE,
"otp-sha384",
"org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList,
emptyMap));
putService(new Service(this, PASSWORD_FACTORY_TYPE,
"otp-sha512",
"org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList,
emptyMap));
putMakedPasswordImplementations(this::putService, this); <==
NPE here
}
The source code for this method can be found in the following source jar
${M2_REPO}/org/wildfly/security/wildfly-elytron-base/2.5.1.Final/wildfly-elytron-base-2.5.1.Final-sources.jar
(where M2_REPO will normally be ~/.m2/repository)
A step at this point entered MethodHandleNative::linkDynamicConstant
which in turn entered into ConstantBootstraps.makeConstant(). The caller
Class at this point is a lambda class which prints as
org.wildfly.security.WildflyElytronBaseProvider$$Lambda/0x800000000c
Several steps further the code enters BootstrapMethodInvoker::invoke
(below the app method call but via 3 hidden frames) with bootstrapMethod
bound to a DirectMethodHandle. After several more steps this enters
DirectMethodHandle$Holder.invokeStatic which in turn calls
MethodHandles::classData(Lookup,String,Class).
At this point caller is a MethodHandleLookup for the lambda class
Lambda/0x800000000c mentioned above. The following call
Object classdata = classData(caller.lookupClass());
returns null to DirectMethodHandle$Holder.invokeStatic which pops the
same result back out to BootstrapMethodInvoker::invoke at line 90
if (type instanceof Class<?> c) {
result = bootstrapMethod.invoke(caller, name, c);
<== null
This null result pops back out as the value for the call to
BootstrapMethodInvoker.invoke(), ConstantBootstraps.makeConstant() and
MethodHandleNative::linkDynamicConstant().
More information about the leyden-dev
mailing list