librelist archives

« back to archive

Supporting -javaagent

Supporting -javaagent

From:
Phil Hagelberg
Date:
2013-05-15 @ 19:11
Hello folks.

I've recently come across a few cases where using -javaagent has proven
fairly awkward in Leiningen projects and am wondering whether we should
add proper first-class support for it. Conceptually they could be
considered top-level artifacts similar to :dependencies and :plugins
where they end up on the `-javaagent` command-line argument instead of
`-classpath` (though they do end up on the classpath).

I was only vaguely aware of -javaagent before yesterday, so I'm still
reading up on the background for it. It sounds like the responsibility
of downloading the jar and placing it on the command-line invocation is
the main thing. Do these jars have transitive dependencies? If so do
they need to go in the -javaagent option as well? Or just on the regular
classpath? It sounds like there are cases where they would need to be
added to the bootclasspath as well; maybe an option in the depedency
vector would be a good way to signal this?

-Phil

Re: [leiningen] Supporting -javaagent

From:
David Powell
Date:
2013-05-16 @ 09:25
I only use agents indirectly in liverepl [1], by injecting them into
running processes with the attach api [2].  I'm still working on
lein-ifying that atm...

In my case, I load in transitive dependencies manually into their own
classloader to avoid poluting the injected process, so dependencies weren't
a concern.

I think agents are often used for things like code coverage tools.  eg [3]

[1] https://github.com/djpowell/liverepl/tree/1.1-alpha
[2]

http://docs.oracle.com/javase/6/docs/jdk/api/attach/spec/com/sun/tools/attach/VirtualMachine.html
[3] http://www.eclemma.org/jacoco/trunk/doc/agent.html

On Wed, May 15, 2013 at 8:11 PM, Phil Hagelberg <phil@hagelb.org> wrote:

>
> Hello folks.
>
> I've recently come across a few cases where using -javaagent has proven
> fairly awkward in Leiningen projects and am wondering whether we should
> add proper first-class support for it. Conceptually they could be
> considered top-level artifacts similar to :dependencies and :plugins
> where they end up on the `-javaagent` command-line argument instead of
> `-classpath` (though they do end up on the classpath).
>
> I was only vaguely aware of -javaagent before yesterday, so I'm still
> reading up on the background for it. It sounds like the responsibility
> of downloading the jar and placing it on the command-line invocation is
> the main thing. Do these jars have transitive dependencies? If so do
> they need to go in the -javaagent option as well? Or just on the regular
> classpath? It sounds like there are cases where they would need to be
> added to the bootclasspath as well; maybe an option in the depedency
> vector would be a good way to signal this?
>
> -Phil
>

Re: [leiningen] Supporting -javaagent

From:
Paul Gearon
Date:
2013-05-16 @ 12:57
My own experience was with a code rewriter (logging entry and exit for
methods in given packages). In that case, the agent jar seemed to require
everything to be included in it, so I unpacked ASM and included it in an
uberjar. I didn't come across another approach, and some brief searching
seems to show that this is the only effective way to get libs onto the
agent classpath (I'd be interested to learn if that's not right).

Consequently, I've used Ant for this. As is usual for Ant, it's annoying to
set up, but it's infinitely flexible. The process involved getting the ASM
jars, including them on the classpath while compiling, extracting them and
jaring them up into the agent jar, and then the agent jar is ready for java
invocation as a -javaagent param. There may be a much better way, but that
worked for me.

Paul

On Thu, May 16, 2013 at 5:25 AM, David Powell <djpowell@djpowell.net> wrote:

> I only use agents indirectly in liverepl [1], by injecting them into
> running processes with the attach api [2].  I'm still working on
> lein-ifying that atm...
>
> In my case, I load in transitive dependencies manually into their own
> classloader to avoid poluting the injected process, so dependencies weren't
> a concern.
>
> I think agents are often used for things like code coverage tools.  eg [3]
>
> [1] https://github.com/djpowell/liverepl/tree/1.1-alpha
> [2]
> 
http://docs.oracle.com/javase/6/docs/jdk/api/attach/spec/com/sun/tools/attach/VirtualMachine.html
> [3] http://www.eclemma.org/jacoco/trunk/doc/agent.html
>
> On Wed, May 15, 2013 at 8:11 PM, Phil Hagelberg <phil@hagelb.org> wrote:
>
>>
>> Hello folks.
>>
>> I've recently come across a few cases where using -javaagent has proven
>> fairly awkward in Leiningen projects and am wondering whether we should
>> add proper first-class support for it. Conceptually they could be
>> considered top-level artifacts similar to :dependencies and :plugins
>> where they end up on the `-javaagent` command-line argument instead of
>> `-classpath` (though they do end up on the classpath).
>>
>> I was only vaguely aware of -javaagent before yesterday, so I'm still
>> reading up on the background for it. It sounds like the responsibility
>> of downloading the jar and placing it on the command-line invocation is
>> the main thing. Do these jars have transitive dependencies? If so do
>> they need to go in the -javaagent option as well? Or just on the regular
>> classpath? It sounds like there are cases where they would need to be
>> added to the bootclasspath as well; maybe an option in the depedency
>> vector would be a good way to signal this?
>>
>> -Phil
>>
>
>

Re: [leiningen] Supporting -javaagent

From:
Phil Hagelberg
Date:
2013-05-16 @ 19:02
Paul Gearon writes:

> My own experience was with a code rewriter (logging entry and exit for
> methods in given packages). In that case, the agent jar seemed to require
> everything to be included in it, so I unpacked ASM and included it in an
> uberjar. I didn't come across another approach, and some brief searching
> seems to show that this is the only effective way to get libs onto the
> agent classpath (I'd be interested to learn if that's not right).

Gotcha; so agent jars essentially must be uberjars. Very interesting.

I think we could probably come up with a way to remove this restriction,
but if all extant agent jars currently work this way, and non-uberjar
agent jars wouldn't work outside Leiningen it's probably not worth it.

> Consequently, I've used Ant for this. As is usual for Ant, it's annoying to
> set up, but it's infinitely flexible. The process involved getting the ASM
> jars, including them on the classpath while compiling, extracting them and
> jaring them up into the agent jar, and then the agent jar is ready for java
> invocation as a -javaagent param. There may be a much better way, but that
> worked for me.

How is this different from making an uberjar?

I've commited initial javaagent support to master. It fetches all the
deps for a :java-agents jar but only places direct dependencies on the
-javaagent argument. I've read that in some cases adding the agent to
the bootclasspath is necessary, so I plan on supporting that as well
before it's considered complete, but if anyone interested could take a
look at what we've got now that would be great:

    https://github.com/technomancy/leiningen/commit/a99d9

thanks

-Phil

Re: [leiningen] Supporting -javaagent

From:
Paul Gearon
Date:
2013-05-17 @ 17:28
On Thu, May 16, 2013 at 3:02 PM, Phil Hagelberg <phil@hagelb.org> wrote:

>
> Paul Gearon writes:
>
> > My own experience was with a code rewriter (logging entry and exit for
> > methods in given packages). In that case, the agent jar seemed to require
> > everything to be included in it, so I unpacked ASM and included it in an
> > uberjar. I didn't come across another approach, and some brief searching
> > seems to show that this is the only effective way to get libs onto the
> > agent classpath (I'd be interested to learn if that's not right).
>
> Gotcha; so agent jars essentially must be uberjars. Very interesting.
>

I can't say that unequivocally, but it seems to be that way. It's been a
while since I looked, but the agent classes appear to be loaded up before
any of the system classes are loaded. If you have the agent print out what
it sees, then you can watch the class loader pick up all the java.lang
classes, including the ones you're already using in the agent (like
java.lang.String). So it seems to be a separate classpath environment.


I think we could probably come up with a way to remove this restriction,
> but if all extant agent jars currently work this way, and non-uberjar
> agent jars wouldn't work outside Leiningen it's probably not worth it.

> Consequently, I've used Ant for this. As is usual for Ant, it's annoying
> to
> > set up, but it's infinitely flexible. The process involved getting the
> ASM
> > jars, including them on the classpath while compiling, extracting them
> and
> > jaring them up into the agent jar, and then the agent jar is ready for
> java
> > invocation as a -javaagent param. There may be a much better way, but
> that
> > worked for me.
>
> How is this different from making an uberjar?
>

It's not. I was just trying to be explicit, sorry.

Paul

Re: [leiningen] Supporting -javaagent

From:
Phil Hagelberg
Date:
2013-05-24 @ 22:31
Thanks for the feedback on this feature. Has anyone gotten a chance to
use it?

I'd like to cut a release of Leiningen which includes this functionality
next week, so I'd love to hear about issues or potential concerns.

thanks,
Phil