Thanks Mandy, I appreciate it! Best regards, Rafael 2018-04-15 8:33 GMT+02:00 mandy chung <mandy.ch...@oracle.com>:
> Hi Rafael, > > FYI. I have sent a proposal [1] for item #1 to serviceability-dev and you > for discussion. JBS issue is: > https://bugs.openjdk.java.net/browse/JDK-8200559 > > Mandy > [1] http://mail.openjdk.java.net/pipermail/serviceability-dev/ > 2018-April/023529.html > > > On 4/2/18 5:02 AM, Rafael Winterhalter wrote: > > 1. Java agents cannot define auxiliary classes. > > Byte Buddy does support the JPMS fully, however, it still relies on > sun.misc.Unsafe::defineClass for its Java agent API and currently breaks on > Java 11 as this method was removed in a recent EA build. The reason for > using Unsafe is that many instrumentations need to define auxiliary classes > to aid an instrumentation similar to javac which sometimes needs to define > anonymous classes or even synthetic classes. For example, if a Java agent > wants to register an event listener to some framework, such listeners often > declare multiple methods what makes it impossible to fullfil the listener > contract using a lambda expression. Instead, one typically injects an > additional class into the same package as the instrumented class. In this > case, it is not possible to use MethodHandles.Lookup::defineClass as the > class file transformer does not necessarily have private access to the > lookup of the instrumented class. > > The current workarounds are: > > a) Open the package jdk.internal.misc to gain access to this package's > Unsafe 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 global > access rights. > > Of these solutions only (b) relies on standard API and is guaranteed to > function in the future but the solution still feels hacky and does not work > for instrumentations of classes on the bootstrap loader. Opening packages > also implies a risk of being applied carelessly since opening the package > to the agent's module most likely opens the package to the unnamed module > of the system class loader what invites to breaches of the JPMS > encapsulation 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 the > Instrumentation interface that works similar to Unsafe::defineClass. This > would provide a very simple migration path. Since agents have access to > jdk.internal.misc, adding this method does not add any capabilities to the > agent, it merley avoids using internal API that might change. > b) Supply a MethodHandles.Lookup instance to the > ClassFileTransformer::transform API where the instance represents the > instrumented class's access rights. This does however carry the risk of > invoking the lookupClass method which would either load the instrumented > class prematurely causing a circularity error or return an unexpected value > such as null. Since the lookup API generally relies on loaded types, there > are probably other problems such as invoking Lookup::privateLookupIn before > all involved types are loaded. > > For the sake of simlicity and since easy migration paths make a quick > adoption easier, I would suggestion solution (a), also in the light that > quick and dirty migrations might still choose option (b) to save time and > also since (b) might cause problems when types are not yet loaded. > > >