Boy is this amazingly difficult. I’m writing it here so I won’t forget. I hope this helps someone else. Hopefully, too, there is a less verbose way to accomplish this.
The excerpt below does private static final MethodHandle gorp = MethodHandles.lookup().findStatic(TestPrivateStaticFinalFieldInitialization.class, "goop", MethodType.methodType(void.class));
in ByteBuddy. *** goop
shows up on the console at the end. I have a StackOverflow post in case this changes.
Awful formatting courtesy of your friends at WordPress:
// Excerpt from JUnit Jupiter unit test whose class is named
// TestPrivateStaticFinalFieldInitialization:
@Test
final void testAll() throws Throwable {
final MethodDescription findStaticMethodDescription = new TypeDescription.ForLoadedType(MethodHandles.Lookup.class)
.getDeclaredMethods()
.filter(ElementMatchers.named("findStatic"))
.getOnly();
final MethodDescription methodHandlesLookupMethodDescription = new TypeDescription.ForLoadedType(MethodHandles.class)
.getDeclaredMethods()
.filter(ElementMatchers.named("lookup"))
.getOnly();
final MethodDescription methodTypeMethodTypeMethodDescription = new TypeDescription.ForLoadedType(MethodType.class)
.getDeclaredMethods()
.filter(ElementMatchers.named("methodType")
.and(ElementMatchers.isStatic()
.and(ElementMatchers.takesArguments(Class.class))))
.getOnly();
final ByteBuddy byteBuddy = new ByteBuddy();
DynamicType.Builder<?> builder = byteBuddy.subclass(Object.class);
builder = builder
.defineField("gorp", MethodHandle.class, Visibility.PRIVATE, Ownership.STATIC, SyntheticState.SYNTHETIC, FieldManifestation.FINAL)
.invokable(ElementMatchers.isTypeInitializer())
.intercept(MethodCall.invoke(findStaticMethodDescription)
.onMethodCall(MethodCall.invoke(methodHandlesLookupMethodDescription))
.with(new TypeDescription.ForLoadedType(TestPrivateStaticFinalFieldInitialization.class))
.with("goop")
.withMethodCall(MethodCall.invoke(methodTypeMethodTypeMethodDescription)
.with(new TypeDescription.ForLoadedType(void.class)))
.setsField(new FieldDescription.Latent(builder.toTypeDescription(),
"gorp",
ModifierContributor.Resolver.of(Visibility.PRIVATE,
Ownership.STATIC,
SyntheticState.SYNTHETIC,
FieldManifestation.FINAL).resolve(),
TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(MethodHandle.class),
Collections.emptyList())));
final Class<?> newClass = builder.make().load(Thread.currentThread().getContextClassLoader()).getLoaded();
final Field gorpField = newClass.getDeclaredField("gorp");
gorpField.setAccessible(true);
final MethodHandle methodHandle = (MethodHandle)gorpField.get(null);
assertNotNull(methodHandle);
methodHandle.invokeExact();
}
public static final void goop() {
System.out.println("*** goop");
}