Reflective access to bytes[] of loaded class
Dan Heidinga
heidinga at redhat.com
Thu Feb 9 16:35:36 UTC 2023
On Thu, Feb 9, 2023 at 11:03 AM Gary Frost <gary.frost at oracle.com> wrote:
> I would like to make a case for adding a reflection API for getting the
> bytes for class loaded by the VM as part of this Classfile API.
>
> Something akin to
>
> byte[] Class.getClassfileBytes();
>
I've often wanted the same kind of API when doing one off tests and minor
modifications so I'm very sympathetic to the request. Typically when doing
more "serious" class modification, I've used the
Instrumentation::retransform API [0] or written a native JVMTI agent [1]
and then such an api to get the current classfile bytes isn't required.
Does this match your typical use cases as well?
The JVM does some interesting handling of classfile bytes in these cases -
it allows non-retransform-capable agents to do a 1 time modification of the
original classfile bytes and then saves those bytes away before passing
them on to the retransform-capable agents. One subsequent retransform
events, those saved bytes are reused and only the retransform-capable
agents get a chance to modify the bytes.
The reason this matters is that existing retransform-capable agents aren't
expecting to see the modifications they've made present in the classfile
bytes they get passed. Providing an easy api to get the currently
executing bytecodes will mean that these agents will now "see" their own
modifications which may result in incompatibilities.
I'd be interested in feedback from existing major agent providers to see
how much of a problem such a change would cause them before pursuing it
unless there's a more common pattern of use I'm unaware of.
[0]
https://cr.openjdk.java.net/~iris/se/17/latestSpec/api/java.instrument/java/lang/instrument/Instrumentation.html#retransformClasses(java.lang.Class..
.)
[1]
https://cr.openjdk.java.net/~iris/se/17/latestSpec/specs/jvmti.html#RetransformClasses
>
>
>
> At present developers usually resort to something like
>
> clazz.getClassLoader().getResourceAsStream(
> clazz.getName().replace(".", "/") + ".class")
>
> Ignoring the fact that we may have just forced an expensive network fetch,
> to bytes that the JVM clearly already has 'squirrelled away' somewhere...
>
> For me this is hugely problematic as there is no guarentee that the bytes
> fetched from such a stream will match the bytes that the JVM is using for
> the class in question....
>
> Java offers all sorts of opportunities (JVMTI agents, Java agents, even
> custom ClassLoaders) for mutating the incoming classfile's bytes. All of
> which the stream fetched via getResourceAsStream() completely sidesteps.
>
See above (or the JVMTI spec) for which bytes get passed through to
agents. The story is more complex than it first appears.
--Dan
>
> This may well be considered 'out of bounds' for the Classfile API, but I
> think we should consider it, as it seems to be something that users of the
> Classfile API will need going forward.
>
> Gary
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/classfile-api-dev/attachments/20230209/b4cbbfbe/attachment-0001.htm>
More information about the classfile-api-dev
mailing list