Consider the DirectMethodHandle$Holder
class. (It is one of the classes returned by Class.forName("java.lang.invoke.DirectMethodHandle").getDeclaredClasses()
, which is documented to return member classes.)
The following assertion fails under JDK 19:
assert Class.forName("java.lang.invoke.DirectMethodHandle$Holder").isMemberClass();
Why? Which rule of section 8.5 does it violate?
Like some of the commenters, I am coming to the conclusion that this is a very weird bug. For example, using some javax.annotation.processing
and some javax.lang.model.*
classes, the following assertion does not fail:
assert NestingKind.MEMBER == ((TypeElement)processingEnvironment.getElementUtils().getTypeElement("java.lang.invoke.DirectMethodHandle.Holder")).getNestingKind();
So the outputs of the mechanisms underpinning the compiler do not agree with the outputs of the reflection machinery. I've filed a bug against the JDK.
As Holger already said, the class file does not correspond to the source code. This class file is overwritten with a different one by a jlink plugin that runs when the JDK is created.
There are several such holder classes in the jdk:
private static final String DIRECT_METHOD_HOLDER_ENTRY =
"/java.base/java/lang/invoke/DirectMethodHandle$Holder.class";
private static final String DELEGATING_METHOD_HOLDER_ENTRY =
"/java.base/java/lang/invoke/DelegatingMethodHandle$Holder.class";
private static final String BASIC_FORMS_HOLDER_ENTRY =
"/java.base/java/lang/invoke/LambdaForm$Holder.class";
private static final String INVOKERS_HOLDER_ENTRY =
"/java.base/java/lang/invoke/Invokers$Holder.class";
These hold the contents of certain pre-generated java.lang.invoke
implementation classes. Pre-generating these classes during jlink-time avoids having to generate them at runtime. So, this is essentially done for performance reasons.