ByteBuddy and private static final fields

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");
  }

On Terminology

The hardest thing in software engineering is naming things.

We have some conventions, but not a lot. Many of those conventions come from design patterns. For example, we have builders and adapters and factories and visitors and so on.

But there are strikingly few conventions about how to name other things. For example, when implementing an interface that consists of a single method that can return something either new or old, what should we call it? The JDK has settled on the term Supplier, which maybe is fine, but then the method is called get, rather than supply. Does get really capture what a Supplier does? Again, naming things is hard.

As another example, sometimes factories assemble things out of raw materials—and then simply return what they’ve assembled, over and over. Is that actually what a factory does? No, it is not. Naming things is hard.

My own personal dictionary includes these concepts and I try to use them very carefully in my own software:

  • A supplier may create something or return a single instance of a prefabricated something, or switch arbitrarily. I avoid producer or provider since they don’t really convey why something is being retrieved or made: when something is supplied, by contrast, it is because there is a need, and the supplying fulfills the need.
  • A factory always creates something.
  • If something is backed, then it is implemented in terms of something else. This lets me do things with the adapter pattern but adapter is a terrible word that doesn’t tell you what is being adapted to what and hence which aspect is more primal.
  • If something is default, then it is usually a straightforward something that can be extended or overridden or otherwise made more complicated or performant or interesting. I try to avoid simple, since simplicity should be an emergent property, not something legislated.
  • I try to avoid the word provision since for very strange reasons in the computer industry it often means to create something out of thin air, rather than its English meaning, which is to stock. (When you provision your pantry, you don’t build the pantry, you put cans on its shelves.)
  • Priority is always always always largest-number-wins. Unlike most bug systems I’ve worked with, in English the highest priority problem is the one deserving the most attention. (If you want smallest-number-wins, you’re probably looking for rank. Avoid the use of ordinal entirely since many projects use it to mean priority, and others use it to mean something roughly akin to an indicator of which item should come out of an array first.)
  • An arbiter is something that takes in two or more inputs that may have some ambiguity (or not) and performs arbitration on them, selecting a single output for further processing.
  • If I am tempted to use the word module in any way, shape or form, then I know I have failed spectacularly in every possible way. Something that is a module is inscrutable, which is a fancy way of saying that you really have no idea what it is. Component is rarely any better. Feature is even worse.
  • Name is usually an indication that I haven’t thought the problem domain through well enough. Same goes for description. Both have inherent localization issues as well.
  • A facet is a selection of notional attributes of some other thing that go together. This is a nice terminology pattern to use to keep your classes small and to encourage composition.
  • Helper is right out. Same goes for util or utils or utility. If I am tempted to write any of these, I write crap instead so that it is quite clear that that is what I am creating.
  • In the realm of configuration, a setting is a name. A value or a setting value is a value for a setting. When you have many settings, you have many names, not many values, or at least you’re not talking about the values. (I deliberately try to avoid configuration and property since these are massively overloaded and confusing: is configuration a bunch of something, or just one thing? Is a property a name-value pair, or just a name? Or just a value?)

I’m sure there’s more where this came from. What are some of your terminology systems?