Tip : Profile an OSGi application with VisualVM

OSGi Logo

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 posts:

  1. Java File Copy Benchmark Updates (once again)
  2. NIO.2 : The new Path API in Java 7
  3. Profile your applications with Java VisualVM
  4. Develop a modular application – The loading
  5. Install the JR environment on Windows
  • J Alkjaer

    You can just use
    -Xbootclasspath/p:${VISUALVM_HOME}/profiler3/lib/jfluid-server.jar
    to “prepend” the jfluid-server.jar to the normal bootclasspath which simplifies the whole thing considerably

    • Anonymous

      Are you sure of that ?

      From what I had tested, it is not enough.

    • Anonymous

      Are you sure of that ?

      From what I had tested, it is not enough.

  • Holger

    Can’t see, why the classes of the profiler should be the first thing on the boot classpath as they are the last classes that are accessed, after the startup of the VM. Therefore, the better choice would be -Xbootclasspath/a:${VISUALVM_HOME}/profiler3/lib/jfluid-server.jar to *append* the path to the boot classpath.
    However, I’m wondering whether the osgi classloader might prevent access from modules to these classes even when they are in the boot classpath as they are not part of the public JFC API. But it might make a difference if the module’s classes refer to the profiling classes at load time or if they are transformed at later time. Tricky…