Hello,I am the/a maintainer of the libraries Byte Buddy, cglib and Mockito withcountless dependencies upstream and I wanted to give a summary of adoptingthe JPMS and migrating away from sun.misc.Unsafe.1. Java agents cannot define auxiliary classes.Byte Buddy does support the JPMS fully, however, it still relies onsun.misc.Unsafe::defineClass for its Java agent API and currently breaks onJava 11 as this method was removed in a recent EA build. The reason forusing Unsafe is that many instrumentations need to define auxiliary classesto aid an instrumentation similar to javac which sometimes needs to defineanonymous classes or even synthetic classes. For example, if a Java agentwants to register an event listener to some framework, such listeners oftendeclare multiple methods what makes it impossible to fullfil the listenercontract using a lambda expression. Instead, one typically injects anadditional class into the same package as the instrumented class. In thiscase, it is not possible to use MethodHandles.Lookup::defineClass as theclass file transformer does not necessarily have private access to thelookup of the instrumented class.The current workarounds are:a) Open the package jdk.internal.misc to gain access to this package'sUnsafe class. This can be done via Instrumentation::redefineModule.b) Open the java.lang package to access ClassLoader via reflection.c) Open the java.lang package to access the internal lookup with globalaccess rights.Of these solutions only (b) relies on standard API and is guaranteed tofunction in the future but the solution still feels hacky and does not workfor instrumentations of classes on the bootstrap loader. Opening packagesalso implies a risk of being applied carelessly since opening the packageto the agent's module most likely opens the package to the unnamed moduleof the system class loader what invites to breaches of the JPMSencapsulation by code that does not ship with the agent.To offer a better solution, I would like to suggest one of the following:a) Add a method defineClass(ClassLoader, byte[], ProtectionDomain) to theInstrumentation interface that works similar to Unsafe::defineClass. Thiswould provide a very simple migration path. Since agents have access tojdk.internal.misc, adding this method does not add any capabilities to theagent, it merley avoids using internal API that might change.b) Supply a MethodHandles.Lookup instance to theClassFileTransformer::transform API where the instance represents theinstrumented class's access rights. This does however carry the risk ofinvoking the lookupClass method which would either load the instrumentedclass prematurely causing a circularity error or return an unexpected valuesuch as null. Since the lookup API generally relies on loaded types, thereare probably other problems such as invoking Lookup::privateLookupIn beforeall involved types are loaded.For the sake of simlicity and since easy migration paths make a quickadoption easier, I would suggestion solution (a), also in the light thatquick and dirty migrations might still choose option (b) to save time andalso since (b) might cause problems when types are not yet loaded.2. Java proxies cannot invoke default methods of proxied interfacesThe Java proxy API does not currently allow the invocation of an overriddendefault method sincethe InvocationHandler API only supplies an instance ofjava.lang.reflection.Method. In Java 8, it was always possible to get holdof method handle of any method of the proxied interface and to specializethe handle on the interface type to invoke the default implementation. Withthe JPMS, even if an interface type is exported, this same type might notbe opened to another module. This implies that if an InvocationHandler isdefined by this module to which the interface is exported, this module'sInvocationHandler cannot resolve a specialized method handle to a defaultmethod of the proxied interface. As a matter of fact, such a call isimpossible in this scenario whereas the same call is possible if the proxyis implemented manually at compile time.As a solution, I suggest to provide an argument to the InvocationHandlerthat represents a lookup instance with the access rights of the proxyclass. Using this lookup, the specialized method handles could be resolved.3. Mocking and serialization libraries still requireUnsafe::allocateInstance.For Mockito, it is required to instantiate any class without invoking aconstructor with potential side-effects. This is of course a groseviolation of Java's general contract for class instantiation but thisfeature is very useful.Using a Java agent, it is already possible to emulate this feature withoutinternal API by instrumenting all constructors of all classes in thehierarchy of a mocked class by transforming all constructors into thefollowing pseudo-code:SomeConstructor(Void arg) { if (MockitoBootHelper.THREAD_LOCAL.isMockInstantiatingMode()) { super(null); // any constructor of the super class with default valuesfor all arguments } else { // original constructor code... }}Before instantiating a mock, the thread local value that is held by abootstrap-loader injected class is set to true such that a side-effect freeconstruction is achieved.This is of course too expensive and has negative effects on performance dueto additional branching and JIT-byte code limits such that one would ratheropen jdk.internal.misc to access the Unsafe instantiation mechanism if aJava agent is already available.However, mocking and serialization libraries are not typically loaded as aJava agent. Also, I think that the actual requirements are different. Mysuggestion here is:a) For serialization libraries, I think that addingMethodHandles.Lookup::newInstance(Class<? extends Serializable>) withstandard deserialization mechanics would be sufficient.b) For mocking libraries, this does not suffice as mocks can be of anyclass. I understand that this breaks encapsulation but for unit tests, Iargue that the benefit of using these libraries outweights the benefit offull encapsulation within a unit test.As Mockito is typically run within a build which uses a JDK, we couldattach to the current VM using the attachment API. Since Java 9, this is nolonger possible to attach to the same VM but instead we start a helper JVMprocess that applies the attachment indirectly. Unfortunately, this is arather costly operation what is especially problematic when running asingle unit test. (The difference to this approach over Unsafe is abouthalf a second on average.)To overcome this, I would like to suggest to:a) Add a method Instrumentation::allocateInstance(Class). Java agents canalready emulate this privilege as described above, this is therefore merelya convenience.b) Add a module jdk.test to JDK 11 with a classJavaTest::getInstrumentation that returns an instrumentation instance forthe current JVM. This module should not be resolved by default but onlywhen requiring it explicitly similar to the EE modules after Java 9.I think this solution carries two benefits:a) Test libraries like Mockito can only be used in a testing scope. Weexperience regularly that Mockito is used in production environments. Thelibrary is not meant for that and we warn and document that this is notintended use but people regularly ignore this directive. By requiring thismodule, this form of abuse would no longer be possible and the JVM couldeven give a meaningful error message if this use was intended.b) The Instrumentation instance can be used for other meaningful testingapproaches. For example, Mockito offers an inline mock maker where themocking logic is inlined into a method body rather then creating asubclass. This approach mainly targets final classes which have become morecommon especially since the Kotlin language became popular. To supply thisalternative mock maker, Mockito attempts attaching an agent to the currentVM (directly or indirectly, depending on the VM's version) which suffersthe additional costs for attaching an agent that I mentioned before.Thanks for reading this and I hope that you can consider these, as oftoday, very practiced use cases. The JPMS migration has gone quite well, Ifind. With these outstanding problems, JDK 11 could be the first releasewhere a majority of Java programs would no longer need to rely on internalAPI.Best regards, Rafael