mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8291065: Creating a VarHandle for a static field triggers class initialization
Reviewed-by: mchung, psandoz
This commit is contained in:
parent
a53345ad03
commit
201e3bcf52
10 changed files with 744 additions and 160 deletions
|
@ -472,7 +472,8 @@ import static java.lang.invoke.MethodHandleStatics.UNSAFE;
|
|||
* @since 9
|
||||
*/
|
||||
public abstract sealed class VarHandle implements Constable
|
||||
permits IndirectVarHandle, VarHandleSegmentViewBase,
|
||||
permits IndirectVarHandle, LazyInitializingVarHandle,
|
||||
VarHandleSegmentViewBase,
|
||||
VarHandleByteArrayAsChars.ByteArrayViewVarHandle,
|
||||
VarHandleByteArrayAsDoubles.ByteArrayViewVarHandle,
|
||||
VarHandleByteArrayAsFloats.ByteArrayViewVarHandle,
|
||||
|
@ -518,10 +519,23 @@ public abstract sealed class VarHandle implements Constable
|
|||
this.exact = exact;
|
||||
}
|
||||
|
||||
RuntimeException unsupported() {
|
||||
return new UnsupportedOperationException();
|
||||
/**
|
||||
* Returns the target VarHandle. Subclasses may override this method to implement
|
||||
* additional logic for example lazily initializing the declaring class of a static field var handle.
|
||||
*/
|
||||
@ForceInline
|
||||
VarHandle target() {
|
||||
return asDirect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the direct target VarHandle. Indirect VarHandle subclasses should implement
|
||||
* this method.
|
||||
*
|
||||
* @see #getMethodHandle(int)
|
||||
* @see #checkAccessModeThenIsDirect(AccessDescriptor)
|
||||
*/
|
||||
@ForceInline
|
||||
VarHandle asDirect() {
|
||||
return this;
|
||||
}
|
||||
|
@ -2062,13 +2076,19 @@ public abstract sealed class VarHandle implements Constable
|
|||
|
||||
/**
|
||||
* Validates that the given access descriptors method type matches up with
|
||||
* the access mode of this VarHandle, then returns if this is a direct
|
||||
* method handle. These operations were grouped together to slightly
|
||||
* the access mode of this VarHandle, then returns if this is direct.
|
||||
* These operations were grouped together to slightly
|
||||
* improve efficiency during startup/warmup.
|
||||
*
|
||||
* A direct VarHandle's VarForm has implementation MemberNames that can
|
||||
* be linked directly. If a VarHandle is indirect, it must override
|
||||
* {@link #isAccessModeSupported} and {@link #getMethodHandleUncached}
|
||||
* which access MemberNames.
|
||||
*
|
||||
* @return true if this is a direct VarHandle, false if it's an indirect
|
||||
* VarHandle.
|
||||
* @throws WrongMethodTypeException if there's an access type mismatch
|
||||
* @see #asDirect()
|
||||
*/
|
||||
@ForceInline
|
||||
boolean checkAccessModeThenIsDirect(VarHandle.AccessDescriptor ad) {
|
||||
|
@ -2144,7 +2164,7 @@ public abstract sealed class VarHandle implements Constable
|
|||
public MethodHandle toMethodHandle(AccessMode accessMode) {
|
||||
if (isAccessModeSupported(accessMode)) {
|
||||
MethodHandle mh = getMethodHandle(accessMode.ordinal());
|
||||
return mh.bindTo(this);
|
||||
return mh.bindTo(asDirect());
|
||||
}
|
||||
else {
|
||||
// Ensure an UnsupportedOperationException is thrown
|
||||
|
@ -2186,6 +2206,14 @@ public abstract sealed class VarHandle implements Constable
|
|||
return mh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a method handle that can be passed the {@linkplain #asDirect() direct}
|
||||
* var handle of this var handle with the given access mode. Pre/postprocessing
|
||||
* such as argument or return value filtering should be done by the returned
|
||||
* method handle.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the access mode is not supported
|
||||
*/
|
||||
MethodHandle getMethodHandleUncached(int mode) {
|
||||
MethodType mt = accessModeType(AccessMode.values()[mode]).
|
||||
insertParameterTypes(0, VarHandle.class);
|
||||
|
@ -2401,13 +2429,13 @@ public abstract sealed class VarHandle implements Constable
|
|||
public VarHandle resolveConstantDesc(MethodHandles.Lookup lookup)
|
||||
throws ReflectiveOperationException {
|
||||
return switch (kind) {
|
||||
case FIELD -> lookup.findVarHandle((Class<?>) declaringClass.resolveConstantDesc(lookup),
|
||||
case FIELD -> lookup.findVarHandle(declaringClass.resolveConstantDesc(lookup),
|
||||
constantName(),
|
||||
(Class<?>) varType.resolveConstantDesc(lookup));
|
||||
case STATIC_FIELD -> lookup.findStaticVarHandle((Class<?>) declaringClass.resolveConstantDesc(lookup),
|
||||
varType.resolveConstantDesc(lookup));
|
||||
case STATIC_FIELD -> lookup.findStaticVarHandle(declaringClass.resolveConstantDesc(lookup),
|
||||
constantName(),
|
||||
(Class<?>) varType.resolveConstantDesc(lookup));
|
||||
case ARRAY -> MethodHandles.arrayElementVarHandle((Class<?>) declaringClass.resolveConstantDesc(lookup));
|
||||
varType.resolveConstantDesc(lookup));
|
||||
case ARRAY -> MethodHandles.arrayElementVarHandle(declaringClass.resolveConstantDesc(lookup));
|
||||
default -> throw new InternalError("Cannot reach here");
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue