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.

-Alan

Reply via email to