ClassFileTransformer does not apply to anonymous classes
rafael.wth at gmail.com
Wed Jan 27 08:44:45 UTC 2016
thank you for your answer. As I said before, I do understand the
concept behind resolving lambda expressions at runtime to not
represent "real classes". I do however still disagree with your
assertion. On the opposite, I argue that the fact that nobody can
expect a certain form of implementation for a lambda expression makes
chaging this form a viable solution in the first place.
After the LambdaMetafactory is instrumented, I know that the returned
class site that produces a lambda creates a "plain old Java class" and
can be instrumented. I also know that I can redefine/retransform such
classes without breaking anything. The only glitch in this
substitution of the LambdaMetafactory is that I still need to use the
Unsafe API and that such classes might no longer be retransformable
after some VM update due to loading the class via
Therefore, I suggest to make classes retransformable only if their
constant pool is not patched, i.e. the third argument is set to null.
This would suffice to allow for the described workarround that people
Finally, I want to stress that there is already a lot of code out
there that uses instrumentation. Until Java 8, any class of a Java
application could be transformed in a canonical manner. Having changed
this behavior is a breaking change to a certain degree since people
cannot longer update their applications without a change in behavior
when lambda expressions are involved. And I do not argue that
instrumenting lambdas is a good idea in the first place but existing
code bases already implement a lot of bad ideas that people need to
work with. Refactorings of existing code are always a consideration of
cost and the harder instrumenting lambdas gets, the uglier the hacks
will become and this is to nobody's benefit. This is why I hope that
you can somehow support this functionality after all.
Thank you for considering this!
Best regards, Rafael
2016-01-27 0:38 GMT+01:00 John Rose <john.r.rose at oracle.com>:
> VM anonymous classes are an implementation detail that is
> opaque to system components except for the lowest layers of
> the JDK runtime and the JVM itself. Transformers and other
> instrumentation should not look inside them expecting to interpose
> on their behavior. Ideally we should not make them visible at all,
> but sometimes it helps (e.g., with single stepping through BCs).
> VM anonymous classes may be (and are) replaced or interchanged
> unpredictably with similar mechanisms, such as JNI-based
> reflection, or indirect invocation via MemberName tokens.
> You can't rely on any of this meaning what you think it means,
> even if it appears to have a classfile structure. Even if you
> were able to "transform" one of these classfiles, it wouldn't
> necessary do what you think it should do, because its structure
> is a private internal-only contract of the JDK and JVM.
> And, as you probably have already noticed, the number and
> structure of these VMAC classfiles change over time.
> We may (at some point) replace the classes with some
> completely different internal representation, which,
> even if it is visible somehow to instrumentation, cannot
> meaningfully be parsed and re-implemented.
> Likewise, lambdas are translated into inner classes, but
> this also can change at any time; the metafactory API
> makes few or no promises as to the internal structure
> of the invokedynamic binding. In fact, some JVMs use
> special polymorphic nodes, instead of the standard
> inner-class translation. Suddenly, some or all of these
> classfiles may disappear, when the runtime begins to
> optimize them differently.
> Please don't lead your users to rely on them.
> I second Vladimir's suggestion, that the only sane way
> to interpose on lambdas is to transform the class that
> defines the lambda (including perhaps the parameters
> of the indy that create the lambda), and not dig into
> system internals. System internals are nothing like
> user code, and cannot be transformed like user code.
> Sorry to bear bad news,
> — John
More information about the core-libs-dev