My proposal of ClassDefiner API allows the java agent to define
auxiliary classes in the same runtime package of the class being
instrumented. You raised other use cases that are not addressed by this
proposal. As Alan replied, the ability to define any arbitrary class
would be an attractive nuisance and we think Instrumentation.defineClass
isn't the right API to add.
I think the proposed ClassDefiner API is useful for the specific use
case (define auxiliary classes in the runtime package of the class being
instrumented). I hold it off and so didn't make 11. For the other use
cases, perhaps we should create JBS issues for further investigation.
Mandy
On 7/2/18 1:41 AM, Rafael Winterhalter wrote:
Hi,
I was wondering if a solution for this problem is still planned for JDK
11 giving the beginning ramp down.
With removing sun.misc.Unsafe::defineClass, Java agents only have an
option to use jdk.internal.misc.Unsafe::defineClass for the use-cases
that I described.
I think it would be a missed opportunity not to offer an alternative as
of JDK 11 as a second migration would make it even less likely that
agents would avoid unsafe API.
Thanks for the information,
best regards, Rafael
mandy chung <[email protected] <mailto:[email protected]>>
schrieb am So., 15. Apr. 2018, 08:23:
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