Review Request JDK-8200559: Java agents doing instrumentation need a means to define auxiliary classes
David Holmes
david.holmes at oracle.com
Mon Apr 16 06:13:51 UTC 2018
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?
Thanks,
David
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 classes
> that are visible and accessible to the instrumented class. Existing agents
> have been using sun.misc.Unsafe::defineClass to define aux classes directly
> or accessing protected ClassLoader::defineClass method with setAccessible to
> suppress the language access check (see [1] 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 class
> 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 should
> 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 being
> 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
> [1] http://mail.openjdk.java.net/pipermail/jdk-dev/2018-January/000405.html
More information about the serviceability-dev
mailing list