>From my perspective as a heavy user of this API in Unsafe today:
>From my experience, the recursive dependency is not a common problem as
auxiliary types normally only reference the instrumented type. Beyond, this
problem is an issue for such explicit dynamic class loading, also when
using a method handle lookup.
I also think it is essential to being able to inject a class into a
non-opened package. Otherwise one could use a method handle. When
instrumenting classes one already has full privilege for all packages as an
agent can open modules. If one opens packages to define a class, this would
however open the package to the agent's module which is typically the
unnamed module. As this cannot be undone, such a requirement might
therefore be counter-productive to its intend.
Best regards, Rafael
David Holmes <david.hol...@oracle.com> schrieb am Mo., 16. Apr. 2018, 08:13:
> Hi Mandy,
> How do you handle dependencies across a set of auxiliary types, i.e if
> you are defining a new class A, and it depends on B (which you also
> intend to define), how will the classloader resolve references from A to
> B when it can't load B itself?
> Is the key capability here the ability to inject a class into a package
> that would otherwise not be open to it? What are the security
> implications here?
> On 15/04/2018 4:23 PM, mandy chung wrote:
> > Background:
> > Java agents support both load time and dynamic instrumentation. At load
> > time,
> > the agent's ClassFileTransformer is invoked to transform class bytes.
> > There is
> > no Class objects at this time. Dynamic instrumentation is when
> > redefineClasses
> > or retransformClasses is used to redefine an existing loaded class. The
> > ClassFileTransformer is invoked with class bytes where the Class object
> > is present.
> > Java agent doing instrumentation needs a means to define auxiliary
> > that are visible and accessible to the instrumented class. Existing
> > have been using sun.misc.Unsafe::defineClass to define aux classes
> > or accessing protected ClassLoader::defineClass method with
> setAccessible to
> > suppress the language access check (see  where this issue was brought
> > up).
> > Instrumentation::appendToBootstrapClassLoaderSearch and
> > appendToSystemClassLoaderSearch
> > APIs are existing means to supply additional classes. It's too limited
> > for example it can't inject a class in the same runtime package as the
> > being transformed.
> > Proposal:
> > This proposes to add a new ClassFileTransformer.transform method taking
> > additional ClassDefiner parameter. A transformer can define additional
> > classes during the transformation process, i.e.
> > when ClassFileTransformer::transform is invoked. Some details:
> > 1. ClassDefiner::defineClass defines a class in the same runtime package
> > as the class being transformed.
> > 2. The class is defined in the same thread as the transformers are being
> > invoked. ClassDefiner::defineClass returns Class object directly
> > before the transformed class is defined.
> > 3. No transformation is applied to classes defined by
> > ClassDefiner::defineClass.
> > The first prototype we did is to collect the auxiliary classes and define
> > them until all transformers are invoked and have these aux classes to go
> > through the transformation pipeline. Several complicated issues would
> > need to be resolved for example timing whether the auxiliary classes
> > be defined before the transformed class (otherwise a potential race where
> > some other thread references the transformed class and cause the code to
> > execute that in turn reference the auxiliary classes. The current
> > implementation has a native reentrancy check that ensure one class is
> > transformed to avoid potential circularity issues. This may need JVM TI
> > support to be reliable.
> > This proposal would allow java agents to migrate from internal API and
> > ClassDefiner to be enhanced in the future.
> > Webrev:
> > http://cr.openjdk.java.net/~mchung/jdk11/webrevs/8200559/webrev.00/
> > Mandy
> >