Tip : Profile an OSGi application with VisualVM

When you develop applications and you've performance problems, it's really interesting to see what can cause this problems. And it that case, the profilers are the most useful tool. By example, we can use VisualVM, packed by default with the Java Virtual Machine. For more information, you can read this introduction to Java VisualVM.

But, when you work with OSGi application, it's not as simple as a normal application. The profiler needs that its class can be found by the profiled classes, but with OSGi, the classloader are restricted by the framework and the classes of the profiler cannot be found.

But there is a workaround using boot class path and boot delegation. You need to do 2 things.

1. Add the classes to the boot class-path

First of all, the classes of the profiler must be present in the application. For that, we use the boot class-path. You must add this library in the boot class-path : ${VISUALVM_HOME}/profiler3/lib/jfluid-server.jar. The boot class-path is configured using the -Xbootclasspath option, but if you just add this option :

-Xbootclasspath:${VISUALVM_HOME}/profiler3/lib/jfluid-server.jar

The classes of the JRE will not be found and you will get that kind of error :

Error occurred during initialization of VM
java/lang/NoClassDefFoundError: java/lang/Object

So we need to keep the default boot class-path. To get this, just launch this program :

public class BootClassPath {
    public static void main(String[] args) {
        System.out.println(System.getProperty("sun.boot.class.path"));
    }
}

And it will give you the default boot class-path. Then, you just have to append it to the jar of VisualVM with ':'. By example, on my computer, it's the option I need :

-Xbootclasspath:/usr/lib/jvm/java-6-sun-1.6.0.20/lib/visualvm/profiler3/lib/jfluid-server.jar:/usr/lib/jvm/java-6-sun-1.6.0.20/jre/lib/resources.jar:/usr/lib/jvm/java-6-sun-1.6.0.20/jre/lib/rt.jar:/usr/lib/jvm/java-6-sun-1.6.0.20/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-6-sun-1.6.0.20/jre/lib/jsse.jar:/usr/lib/jvm/java-6-sun-1.6.0.20/jre/lib/jce.jar:/usr/lib/jvm/java-6-sun-1.6.0.20/jre/lib/charsets.jar:/usr/lib/jvm/java-6-sun-1.6.0.20/jre/classes
2. Add boot delegation to the OSGi framework

This is easier. Here you just have to said to the OSGi container, to made the classes of the profiler available to all bundles. For that, you need to add this property :

-Dorg.osgi.framework.bootdelegation=org.netbeans.lib.profiler,org.netbeans.lib.profiler.*

And normally, it's enough. But some OSGi containers, like Felix, doesn't take the command line properties in consideration in the framework depending on how you launch it. In my case, I embed the Felix Server in my application, so I need to explicitly add this property to the framework. For that, read the documentation of the containers to know how to add properties to the framework.

Here we are. Hope this will be useful to someone. Personally, I lost a lot of time trying several configurations before finding this successful one.

Related articles

  • OSGi 4.2 Entreprise Release is available !
  • Modular Java – Book Review
  • Profile your applications with Java VisualVM
  • OSGi - Simple Hello World with services
  • JTheque is going to OSGi
  • Discover Java VisualVM 1.3
  • Comments

    Comments powered by Disqus