RFR: 8200559: Java agents doing instrumentation need a means to define auxilary classes

Alan Bateman Alan.Bateman at oracle.com
Sun Apr 18 16:24:04 UTC 2021

On 16/04/2021 21:09, Rafael Winterhalter wrote:
> I have never seen a need for a non-agent to define a class in a
> non-existing package. Injection is typically required if you want to work
> with package-private types or methods which is really only relevant for the
> Spring framework, but even there I do not think it's such a big area that
> it cannot be addressed. Non-agent code generation is typically the use of
> proxies where the code generation framework is sharing a class loader with
> the user code and there is normally a way to weave it. Agents on the other
> hand have to deal with unknown class loader hierarchies and it can be
> necessary to inject code into a common class loader parent without
> instrumenting classes in this loader or even knowing any classes of this
> loader.
Yes, the injection of proxy classes and the like is mainly the same 
run-time package as an existing class and these are the use-cases that 
Lookup.defineClass and Lookup.defineHiddenClass are intended for. There 
has been a few requests for defining proxy classes into "new/empty 
packages" but has a few challenges, like extending the set of packages 
in a named module. In general I wouldn't expect Java agents, which was 
intending for tools, to be using Lookup objects.

> I have never heard about a 'discussion [that] will eventually lead into
> putting at least some restrictions on agents loaded into a running VM' and
> as a heavy user and someone who has helped to write a long row of
> commercial agents and followed them into their use in production and who
> has seen how helpful they are in reducing deployment complexity, I can only
> hope that you will change your mind on this.
> :
> That said, even if it was restricted in the future, this would mean that
> some of the Instrumentation API methods will throw exceptions in the
> future. There would not be much difference if an introduced defineClass
> method would do the same.
There was fuss on this topic during JDK 9. I'll try to find the mails in 
the archive, it would have been on serviceability-dev in 2016 or 2017. 
The compromise at the time was to introduce the 
-XX:EnableDynamicAgentLoading option with an initial value of "true" and 
re-visit it later. Flipping the default would mean that JVMTI and Java 
agents could not be loaded into a target VM without opt-in on the 
command line. No impact to agents specified on the command line with 
-javaagent, no impact to other usages of the attach mechanism so jcmd 
and the other diagnostic tools would continue to work.

To re-cap, the main concern is the Instrumentation object is 
all-powerful and is intended for tools and the instrumentation is 
intended to be benign to support use-cases such as monitoring and 
tracing. It was never intended to a back-door into JDK internals. 
Specifying an agent on the command line with -javaagent is the opt-in to 
trust that agent. A tool run by the same user that loads its agent into 
a target VM is the use-case we targeted when we added the attach 
mechanism and the late binding agent support in JDK 6. The issue with 
that (and it's a regret now) is that the mechanism doesn't distinguish 
usage by a tool from a library/application using the attach mechanism to 
load an agent into the current VM (directly or using an intermediate VM).

Time has moved on and maybe a better approach is to not change the XX 
option but instead load the agents with reduced capabilities. It would 
require opt-in on the command line to give these agents the same 
capabilities as agents specified on the command line with -javaagent. It 
would require exploration but it might be that unrecognized agents would 
not be allowed to redefine java.base or other core modules or instrument 
classes in those modules. The APIs are already specified to allow 
Unmodified{Module,Class}Exception be thrown as there have been cases in 
the past where some classes could not be transformed. Project Panama is 
currently exploring how to restrict and grant access to native code and 
maybe it should be the same mechanism or at least be consistent.

Hopefully this helps sets some context as to why we have to be cautious 
with this PR. If the proposal were a defineClass that was limited to 
agents specified on the command line then it might okay. This would 
serve use-cases with tool agents that are way more advanced that the 
use-cases that we envisaged back in Java 5/6. The previous exploration 
into allowing non-public auxiliary classes be defined in the same 
run-time package as the class being instrumented was also okay.


More information about the core-libs-dev mailing list