ByteBuddyAgent and OSGI

366 views
Skip to first unread message

odbu...@gmail.com

unread,
Nov 29, 2015, 1:06:25 AM11/29/15
to Byte Buddy
byte-buddy-0.7.1

I'm successfully using ByteBuddyAgent in a regular java application but I'm having trouble using it with OSGI.  I've tried installing the agent with a transformer before OSGI is initialized and in an Activator on Bundle startup but the transformer is not doing anything.  Do you have any examples of how to yse ByteBuddyAgent with OSGI?

Rafael Winterhalter

unread,
Nov 30, 2015, 3:18:29 AM11/30/15
to odbu...@gmail.com, Byte Buddy

Hi,

OSGi is built on top of standard Java, a Java agent should therefore function as usual.

However, you still need to run your agent on startup of the OSGi container using the javaagent parameter. You cannot bundle an agent as the OSGi container does not trigger agents.

Cheers, Rafael

Am 29.11.2015 7:06 vorm. schrieb <odbu...@gmail.com>:
byte-buddy-0.7.1

I'm successfully using ByteBuddyAgent in a regular java application but I'm having trouble using it with OSGI.  I've tried installing the agent with a transformer before OSGI is initialized and in an Activator on Bundle startup but the transformer is not doing anything.  Do you have any examples of how to yse ByteBuddyAgent with OSGI?

--
You received this message because you are subscribed to the Google Groups "Byte Buddy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to byte-buddy+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

odbu...@gmail.com

unread,
Nov 30, 2015, 11:16:26 AM11/30/15
to Byte Buddy
byte-buddy-0.7.1
equinox

I understand this but let me explain further.  I have Equinox and byte-buddy-agent.jar on the classpath when I start the application.  In the main method I install the agent using:

ByteBuddyAgent.install();

Then I start the OSGI container programmatically.  Bundles are installed (including byte-buddy.jar).
Then inside of one of my bundle's Activator, I install a transformer like this (and others that have been tested outside of OSGI and work):

        new AgentBuilder.Default()
               
.type(ElementMatchers.is(CLASS))
               
.transform(new AgentBuilder.Transformer() {
                   
@Override
                   
public DynamicType.Builder transform(DynamicType.Builder builder, TypeDescription typeDescription) {
                       
System.out.format("Transforming %s", typeDescription.getName());
                       
return builder
                               
.constructor(any())
                               
.intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.to(new Object() {
                                   
public void m(@This Object o) {
                                       
System.out.format("After constructor %s%n", o.getClass().getName());
                                   
}
                               
})));
                   
}
               
}).installOnByteBuddyAgent();


Then I create a class that hasn't been loaded yet and the transformer is not used.

I've also tried installing the following:
Start OSGI (bundles installed including byte-buddy-agent and byte-buddy)
Start a bundle which does the following in an Activator:
  ByteBuddyAgent.install();
  Install the transformer as above

That does not work either.

Rafael Winterhalter

unread,
Nov 30, 2015, 12:14:36 PM11/30/15
to odbu...@gmail.com, Byte Buddy

This might be a visibility issue. Your interceptor is package private. Please register a listener to your agent builder and see if there is any problem. This way, you also have a relyable way of finding out if your type is considered for instrumentation.

--

odbu...@gmail.com

unread,
Nov 30, 2015, 1:44:07 PM11/30/15
to Byte Buddy, odbu...@gmail.com
I tested again with the interceptors available to the java application classpath and to all of the bundles (and verified during runtime that this is true) and it still doesn't work.

Are both byte-buddy and byte-buddy-agent supposed to be on the java application classpath for this to work?  I was going to test with byte-buddy on the application classpath and then installing the transformer before the OSGI container is started but that would defeat the purpose of the byte-buddy jars being bundles...

Does someone have this working in an OSGI container?

Rafael Winterhalter

unread,
Nov 30, 2015, 2:46:04 PM11/30/15
to odbu...@gmail.com, Byte Buddy
You are right, I just double-checked and there is a OSGi related bug. Can you build Byte Buddy from master and try if everything works as expected?

mvn install -Pextras

does the job. Here is what is happening:

Byte Buddy can be used for example for subclass instrumentation where bundeling makes perfect sense.

As for Java agents: They do not fit into the OSGi model to the extend that Java agents must be:
a) Registered at VM startup (not at bundle startup)
b) Run on the system class path

This is a requirement that is imposed by the JVM and OSGi, as application running on the Java virtual machine cannot overcome this limitation.

However, Byte Buddy has mechanisms to attach an agent at runtime, even when it is not run on the class path (ByteBuddyAgent.install()). Here I made a mistake that would cause an exception to be thrown prematurely on OSGi containers.

I just released a new version but if you can verify that this works for you now, then I release another version some time this week.
Cheers, Rafael

odbu...@gmail.com

unread,
Nov 30, 2015, 2:54:57 PM11/30/15
to Byte Buddy, odbu...@gmail.com
So I should be able to:

start the java app
install byte-buddy and byte-buddy-agent (and my jars) as bundles
start one of my bundles which runs:
  ByteBuddyAgent.install()
  new AgentBuilder.Default().....installOnByteBuddyAgent();

But the interceptors need to be on the application classpath?  If this is true, this still makes it difficult to use b/c the interceptors often require byte-buddy annotations at runtime from byte-buddy.jar which means byte-buddy.jar needs to be on the system classpath... not to mention that the interceptor implementations often need classes which I'd normally put in my bundles, not on the application classpath.

Rafael Winterhalter

unread,
Nov 30, 2015, 3:18:57 PM11/30/15
to odbu...@gmail.com, Byte Buddy
As long as you run your application on a JDK, you can now (recent push, 2 minutes ago) successfully use Byte Buddy on OSGi by calling ByteBuddy.install() from for example your bundle activator and register your agent.

This is however not possible on non-JDK VMs. In this case, you have to start your JVM running OSGi with -javaagent:byte-buddy-agent.jar
Other than that, you can leave your application unaltered because no classes of a bundle are loaded before executing the bundle's activator. You can then again register an agent and as long as you only try to instrument classes from you own bunldle, everything should work out fine.

Cheers, Rafael

odbu...@gmail.com

unread,
Nov 30, 2015, 7:59:34 PM11/30/15
to Byte Buddy, odbu...@gmail.com
I tried it and it works. I was able to use byte-buddy and byte-buddy-agent jars as bundles.  In my bundle I installed the agent and installed an interceptor which referred to annotations and classes within the bundle and it worked.
Reply all
Reply to author
Forward
0 new messages