Disallowing the dynamic loading of agents by default (revised)

classic Classic list List threaded Threaded
24 messages Options
12
Reply | Threaded
Open this post in threaded view
|

RE: Disallowing the dynamic loading of agents by default (revised)

Stephen Felts
The description below leaves out the " ancestor of the current process".
Which way is it - do we need to start two processes or one to work around this?


-----Original Message-----
From: Alan Bateman
Sent: Monday, April 10, 2017 2:39 PM
To: [hidden email]
Subject: Re: Disallowing the dynamic loading of agents by default (revised)

The Jigsaw EA builds [1] have been refreshed to include some of the pieces in this proposal, specifically:

- If an executable JAR contains a java agent then it will be started by `java -jar` when the main manifest has the `Launcher-Agent-Class` attribute. The entry point that is invoked is the `agentmain` method. In the HotSpot implementation then all Can-XXX attributes can be used. The Boot-Class-Path attribute can be used too, say for cases where the executable JAR brings a helper JAR with classes that need to be visible to the boot loader (when instrumenting classes in modules defined to the boot loader for example).

The `Launcher-Agent-Class` attribute will be ignored when on small run-time image that doesn't include the `java.instrument` module.

One other point to mention is that the proposal (and implementation) does not include any built-in support for providing options to the agent. If configuration is needed then one simple approach is to include a resource file in the JAR file with the options and have the agent read that with Class.getResourceXXX.

- The attach API disallows attaching to the current process. For now, the "jdk.attach.allowAttachSelf" system property can be used for cases where the tool and target VM are the same process. The system property is set on the command line with `-Djdk.attach.allowAttachSelf` or `-Djdk.attach.allowAttachSelf=true`. It will be ignored on JDK 8 and older.

The builds don't have the Serguei Spitsyn's patch for EnableDynamicAgentLoading yet. We're re-align that with the revised proposal so that there are builds available to try out in the coming days.

-Alan

[1] https://jdk9.java.net/jigsaw/

Reply | Threaded
Open this post in threaded view
|

Re: Disallowing the dynamic loading of agents by default (revised)

Alan Bateman
On 11/04/2017 05:31, Stephen Felts wrote:

> The description below leaves out the " ancestor of the current process".
> Which way is it - do we need to start two processes or one to work around this?
>
The thread moved one from the original proposal. The only requirement
now is that the tool and target VMs are different.

-Alan
Reply | Threaded
Open this post in threaded view
|

RE: Disallowing the dynamic loading of agents by default (revised)

Stephen Felts
I ran into another tool that is broken with this proposal (someone can update https://docs.google.com/document/d/19H1iGUnyI4Y40U5sNVAmH0uLxcpNfYSjPIW3s0Rv5Ss/edit?usp=sharing again).

Mockito is now broken again.  It's sad because they recently fixed the 2.x version to run cleanly on JDK 9 and I had just upgraded for that reason.

 

The proposed use of java -jar or the command line property don't work because mockito doesn't own either of these.  It's buried deep in gradle calls junit calls mockit.  This particular set of tests is doing a fork per test.

The start a new process per occurrence is ugly if it works at all and we don't really want every tool in my JVM to be doing this for performance and memory reasons.

 

While a huge amount of JDK9 breakage is based on the one line sentence not to use sun.* classes, this breakage doesn't fit.  This is a documented feature that was in fact enhanced to add this API in JDK 6.

Apparently a lot of products are using it to do self-attach and there is no restriction on that for JDK 6-8.

 

This is admittedly a short term fix since there isn't time to do a correct fix in JDK9 and it should wait until JDK 10 to be done correctly.

 

 

 

    Caused by: java.io.IOException: Can not attach to current VM

        at jdk.attach/sun.tools.attach.HotSpotVirtualMachine.<init>(HotSpotVirtualMachine.java:75)

        at jdk.attach/sun.tools.attach.VirtualMachineImpl.<init>(VirtualMachineImpl.java:56)

        at jdk.attach/sun.tools.attach.AttachProviderImpl.attachVirtualMachine(AttachProviderImpl.java:58)

        at jdk.attach/com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:207)

        at mockit.internal.startup.AgentLoader.attachToRunningVM(AgentLoader.java:146)

 

 

-----Original Message-----
From: Alan Bateman
Sent: Tuesday, April 11, 2017 3:01 AM
To: Stephen Felts; [hidden email]
Subject: Re: Disallowing the dynamic loading of agents by default (revised)

 

On 11/04/2017 05:31, Stephen Felts wrote:

 

> The description below leaves out the " ancestor of the current process".

> Which way is it - do we need to start two processes or one to work around this?

>

The thread moved one from the original proposal. The only requirement now is that the tool and target VMs are different.

 

-Alan

 
Reply | Threaded
Open this post in threaded view
|

Re: Disallowing the dynamic loading of agents by default (revised)

rliesenfeld
This post has NOT been accepted by the mailing list yet.
In reply to this post by Alan Bateman
I want to point out that libraries (like JMockit) that rely on self-attaching are only doing so in order to work around a limitation in the java.lang.instrument API.

Namely, that it fails to provide an "InstrumentationFactory#newInstrumentation()" class & method, which is what mocking (JMockit), code coverage (JMockit, JaCoCo), and other bytecode manipulation tools (Byteman, JBoss AOP, AspectJ in runtime weaving mode) actually need. Other APIs in Java SE commonly provide such factories: JDBC, JPA, XML, etc. So, why not the Instrumentation API? There is no need to load a Java agent (well, there is the matter of the "premain/agentmain" entry point it provides, but that is a different issue).

Such a "newInstrumentation()" method, if added, would be a native method creating a "new InstrumentationImpl(x)" object, where "x" is a native pointer to an internal C struct only known to JVM internals.

I think this is a perfectly reasonable request, since it turned out that the main use case for the Instrumentation API was *not* its use in external tools like JConsole, but in libraries used by an application, where they need to manipulate the bytecode (through class transformation or redefinition) of the application's own classes in order to provide various runtime facilities (mocking, insertion of coverage counters, method/constructor call interception, decoration, tracing, aspects, etc. - none of these need the "Java agent" part).
12