Over the recent years, I have leveraged especially invokedynamic when instrumenting code. For example, when adding some additional behavior to a method, a Java agent can add an invokedynamic instruction to the beginning or the end of it. Of course, the bootstrap method is also supplied by the agent. The obvious advantage is that the bootstrap method can bind a handle that points to any class loader, which is often an issue when instrumenting applications that can use very custom hierarchies of class loaders. Also, the bootstrap method can create a new class loader as a child of both the instrumented class and the agent’s class loader. This allows them to write instrumentation code that interacts with both the agent and the instrumented class. This makes it possible to define auxiliary classes, for example when a reactive framework needs a callback, without the need of class injection.
The remaining issue however is the bootstrap method. The instrumentation API already offers a way of injecting classes into the bootstrap class loader, which is of course the right place for such a class-loader universal dispatcher. However, with the module system, an instrumented class that is within a named module will not be able to read this bootstrap class. And it is neither possible (without using internal API) to add a class to the java.base module that would indeed be visible to all classes, similar to the lambda metafactory. This leaves me with using the unnamed module of the bootstrap class path, but this requires importing the module from all named modules of instrumented classes, something that becomes a visible reflective change to all code. And which is something I would ideally want to avoid, also because it might interfere with other code that uses the unnamed module of the boot loader. Which brings me to my question; should it be possible to invoke a bootstrap method without applying module checks? In a way, the bootstrap method is not a real part of a class, but a mechanism to set up the class. Once it is initialized, there is no more need to read the module of the bootstrap loader, so ideally it should not be needed to permanently alter the module graph. As an alternative idea, I was wondering if it would be an idea to add a “generic bootstrap method” to the java.base module. The bootstrap method could look something like the following: @FunctionalInterface interface GenericMetafactory { ConcurrentMap<String, GenericMetafactory> factory; static CallSite metafactory(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, String identifier, Object… args) { factory.get(identifier).apply(caller, invokedName, args); } CallSite apply(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, Object… args); } This way, a Java agent could register a dispatcher identified on a random string prior to instrumenting any code and then add invokedyanmic call sites with this string to all instrumented code. Since this bootstrap class lives in the java.base module, no more adjustments would be necessary. A similar generic bootstrapper could be supplied for use for dynamic constants. Thanks, Rafael