Disallowing the dynamic loading of agents by default

Alasdair Nottingham alasdair.nottingham at gmail.com
Tue Apr 4 13:02:28 UTC 2017

> On Apr 3, 2017, at 6:59 PM, mark.reinhold at oracle.com wrote:
> 2017/4/3 10:52:02 -0700, alasdair.nottingham at gmail.com:
>> I’m the lead for WebSphere Liberty at IBM. Liberty uses a java agent,
>> and this proposal will affect us. Our Java Agent is used to update the
>> bytecode of our classes to add in instrumentation for debug logging
>> and performance monitoring. In general it is attached via -javaagent,
>> which wont be affected by this proposal. However there is one case
>> where we do a dynamic attach of this agent. There is an industry trend
>> towards running the application server as an uber-jar using java -jar
>> <jar.name>. To support this in Liberty (in common with other
>> application servers) our main method extracts the app server to disk
>> at startup before bootstrapping the server from extracted jar
>> files. One of the jar files extracted in this way is our Java agent,
>> so we use the attach API to attach it so we get monitoring and debug
>> logging. I had been thinking of expanding this to use the attach api
>> in preference to -javaagent because that gets rid of this spurious
>> error message from the mac JVM:
>> objc[56755]: Class JavaLaunchHelper is implemented in both
>> /Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/bin/java
>> (0x10f4464c0) and
>> /Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/libinstrument.dylib
>> (0x110dbb4e0). One of the two will be used. Which one is undefined.
> Is getting rid of this spurious message (which, as Alan observed, has
> been removed) your only motivation to load the agent dynamically?

No, as I described the motivation for our first use of attach to add a Java agent was to
address our uber-jar deployment. I wanted to use a single JVM, but I wanted the Java
agent to be in the uber-jar and I did not want to have to require the end user to specify
-javaagent as well as -jar. The user experience I wanted to enable was java -jar uber.jar, 
but still have the agent. While I was making this change I noticed that when I dynamically
attached the agent I didn’t get the error message I included. As I didn’t know that the JDK
bug had been finally fixed I was thinking of doing a dynamic attach simply to remove the
error message. I’m assuming that if I thought this way it is likely someone else did also.

>> ...
>> I’d like to add my support to Andrew’s points. I think they are well
>> made and cover my concerns with the proposals well. I’d like to add my
>> thoughts as well though.
> Thanks.  I think my reply to Andrew of a few minutes ago covers most of
> your points too, so I won't repeat myself here.
>> ...
>> Mark did ask for alternative proposals, so other than the defer to a
>> future release option, what about allowing a developer to put
>> something in the manifest.mf to enable dynamic attachment from the
>> same JVM? If there is a concern over all or nothing being too broad
>> the manifest entry could list a hash of the agent jar so the developer
>> has to know about the agent a-priori.
> I don't see how this would address the scenario of a dynamically-loaded
> agent (for, say, performance monitoring) that's unknown to the original
> library or application developer.  This seems to be an important use
> case.

It doesn’t, and I didn’t intend to suggest it would. Essentially I was assuming that
a remote attach and enable of a Java Agent would work, thus allowing performance
monitoring to work, but it would close the aperture for a self-attach, that is agents
that a developer has specifically blessed at the point the jar was built. This would
ensure that if an app developer used a library that did something nefarious with an agent
that the agent wouldn’t work without an app developer specifically acknowledging it.

One of the problems Java has today is that it is very easy to end up depending on internals
because the JVM has no modularity. It is one thing to end up using a Java API that is 
visible, but not intended to be used by an application, and another to explicitly break
the modularity constraints in order to call API’s that are not intended to be accessible. If 
someone does write an agent, to break out of the modularity constraints, I do not think anyone
can validly complain if a change breaks what they are doing. The creation of the agent is
essentially an acceptance they have done something that could be broken at any time. 
Essentially I’m leaning back on I don’t think this is a likely vector for someone attempting
to subvert the modularity system for the long term. Perhaps I’m just being too optimistic, but
in my work on non-modular app servers, and modular app servers it is clear that if you put in
place protection designed to stop accidental use (but not determined malicious use), then it 
causes people to think twice about breaking out of the constraints.

> - Mark

More information about the jigsaw-dev mailing list