Proposals for some open JPMS issues, #ReflectiveAccessByInstrumentationAgents

Andrew Dinn adinn at redhat.com
Mon Jul 4 12:26:34 UTC 2016


On 28/06/16 22:47, mark.reinhold at oracle.com wrote:
> FYI, I've just posted proposals for some of the open issues in the
> draft JPMS specification, including:
>   . . .
>   #ReflectiveAccessByInstrumentationAgents
>   . . .

I am not sure the proposed solution is going to work for my agent and it
may well be a problem for other agents for a similar reason. At root,
the problem is that the new API seems to be tackling a different problem
to the one which motivated me to raise this issue.

The new API allows an agent to rewrite any arbitrary module M so that it
exports a previously hidden package P to some other module M'.
Exercising this API would indeed be sufficient to allow methods of
classes in M' to obtain references to non-public methods/fields of
classes in package P, enable access and then invoke/access them via
reflection. It would also allow the enabled references to be selectively
handed on to other code which the agent might want to be able to employ
reflection. My problem is not with the functionality per se rather with
the provenance of module M'.

As I understand the current situation (after conversations with Alan
Bateman) all agent classes loaded from an agent jar -- whether the agent
is deployed on the command line or dynamically, using the VM_Attach API
-- will belong to the unnamed module _M. My problem turns on the
question what is the relation between M' and _M?

In my case it is my agent code itself that needs to be able to perform
reflective accesses. The agent does not need to provide any modules that
belong to user code or JDK runtime code with the ability to perform
reflective access. So, in my case it is only classes in _M that I want
to be grant the opportunity to perform the reflective access.

Clearly, I don't want to make M' == _M i.e. to export P to all classes
in the unnamed module _M. That would be a serious security flaw. Indeed,
in general, the idea that an agent will take some module M' and provide
all classes in M' with access to classes in package P is only going to
work when the agent has some level of trust in the code in module M'.

I can imagine cases where, say, that might occur for a module that is
not part of the agent per se -- e.g. module M' is part of some
middleware layer whose behaviour has some guarantee of reliability.
However, in most cases it is going to be the case that the code in
module M' is directly related to the agent code and must be deployed
along with the agent. It is highly unlikely that an agent will want to
grant some arbitrary user module wholesale access to a package of some
other module. Restricted export to the agent itself is certainly the
only option in my case. So, with this proposed API my agent would itself
need to provide a module M' and only need it in order to delegate
requests which enable reflective member access. It is immaterial whether
the reflective access itself is performed by the code in module M' or by
agent code.

This presents two problems, one merely awkward, the other a
show-stopper. My agent will need to provide two deliverables, the agent
jar and a module. So, for command line use of the agent, my users will
need to be able to configure deployment of both deliverables. This
complicates usage and also requires different usage if users need to
switch from a pre-Jigsaw to a Jigsaw-enabled JDK (it is common for
Byteman to be used in environments where more than one JDK is
installed). I may be able to mitigate this complexity using convenience
scripts (as I have done already to deal with the difficulty many Byteman
users face configuring the existing javaagent option).

Secondly, and far more importantly, there does not appear to be a way to
deploy both the agent jar and an accompanying module dynamically. I
don't see any option for adding the required agent module M' to the
module path after start-up. This is a show-stopper because 99% of
Byteman usage involves dynamic loading of the agent. I don't doubt that
this will also be a show-stopper for many other agents.

What are the alternatives?

Perhaps Instrumentation needs to provide an API to add a module to the
module path at runtime?

Alternatively, perhaps the proposed API could be used to define a new
module at runtime as well as to redefine an existing one? That still
leaves the question of how to populate that module with one or more classes.

regards,


Andrew Dinn
-----------
Senior Principal Software Engineer
Red Hat UK Ltd
Registered in England and Wales under Company Registration No. 03798903
Directors: Michael Cunningham, Michael ("Mike") O'Neill, Eric Shander


More information about the jigsaw-dev mailing list