I have implemented support for Lookup::defineClass in my library Byte Buddy and my first impression is quite positive, I think this can offer a great alternative for at least some use cases.
For this to work, I do however think it is crucial to add a parameter to the ClassFileTransformer::transform method where a lookup object should be provided as an additional argument in order to allow defining additional classes in the instrumented class's loader and module. In practice, this is often required in the same manner as javac needs to be able to define anonymous classes when compiling source code. I checked my use of Unsafe in Java agents and basically any use case breaks down to defining such classes which can be replaced by Lookup::defineClass if a lookup object with the instrumented class's context would be supplied to the class file transformer. I do neither see that this could yield a security problem as any such priviledge could already be abused by changing the instrumented class. As for the creation of runtime proxies by subclassing, I do not think that this approach offers an alternative. As a library author, I do not normally have an appropriate lookup context available. For use cases like Hibernate or Spring, I think that it is therefore easiest to define a class in a seperate class loader and to require users to export their types to enable AOP. In the end, I do not think that might be a bad thing in the long run. For testing libraries like Mockito, I would however prefer to use a mechanism similar to Unsafe::defineClass. My prefered way would be to add a test-specific module to any JDK installation that needs to be enabled by some flag. It would be too bad if people had to open their modules just for some test code to run where defining a class in a tested class's class loader (for example because it is package-private) is a legitimate demand. Requiring users to explicitly supply a lookup instance would yield an awkward API where I would prefer a parameter (in a way, such a parameter already exists by explicitly opening the Unsafe class via the command line if that class became unavailable in Java 10). By adding a standard testing module, we could however avoid to depend on internal packages and increase stability of our libraries. In such a module, I would also like to see a factory for getting hold of an instrumentation instance for the current VM. I think that other tooling libraries and testing libraries would benefit of such a priviledge module that needs explicit enabling. Keep up the good work! Best regards, Rafael