An example of using VTune™ Amplifier XE to profile Java class called by C/C++ application (JNI)

Since Version 2013 Update 4, the VTune(TM) Amplifier XE performance profiler has supported profiling Java* applications using Launch Application and Attach to Process target configurations with both software- and hardware-based analysis types.

However, it may be that the application uses Java code but is not a Java application. For example, a Java code can be called from within Apache*, Tomcat*, PHP*, MySQL*, etc.  Sometimes, C/C++ code may call Java methods via the Java Native Interface (JNI). This article demonstrates how to profile the Java code of such an application using the VTune Amplifier XE performance profiler.

Steps: (see attached example) 

  1. Create a simple Java class that has a 'calc' public method. See attached Demo.java file
  2. Use Oracle* JDK 1.7 or newer to compile Demo.java with '-g' option (generate symbol information in class file):
    $ ../../jdk1.7.0_11/bin/javac -g Demo.java
  3. Run Demo class directly, ensure it works properly
    $ ../../jdk1.7.0_11/bin/java Demo
    Note that 'main' public method calls 'calc' method in this case.
  4. Specify the function signatures while obtaining the method IDs. To obtain the correct method signature, you can use the following Java command:
    $ ../../jdk1.7.0_11/bin/javap -s -p Demo
    Compiled from "Demo.java"
    public class Demo {
      public Demo();
        Signature: ()V
      public static void main(java.lang.String[]);
        Signature: ([Ljava/lang/String;)V
      public static void calc();
        Signature: ()V
    }
  5. Create a test.cpp C++ file (see attached example) that uses the 'calc' method signature.  See this line in the example cpp file:
    mid = env->GetStaticMethodID(cls, "calc", "()V");
  6. Compile the C++ file to generate an executable:
    $ g++ -g test.cpp -o test -I/home/peter/jdk1.7.0_11/include -I/home/peter/jdk1.7.0_11/include/linux -L/home/peter/jdk1.7.0_11/jre/lib/amd64/server -ljvm
  7. Run the generated executable that calls the public method 'calc' in the Demo class:
    1. Add the JRE library into environment variable LD_LIBRARY_PATH
      $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/peter/jdk1.7.0_11/jre/lib/amd64/server
    2. Run './test' to ensure it calls the Java method properly.
  8. Profile the 'calc' Java method called by the C++ 'test' application with VTune Amplifier:
    $ amplxe-cl -collect hotspots -mrte-mode=auto -- ./test
    $ amplxe-cl -report callstacks
    amplxe-cl -report callstack samplxe: Using result path `/home/peter/JNI/r000hs'
    amplxe: Executing actions 50 % Generating a report
    Function                     Call Stack                            Module                              CPU Time:Self
    ---------------------------  ------------------------------------  ----------------------------------  -------------
    Demo::calc                                                         [Compiled Java code]                19.680
    
                                 call_stub                             [Dynamic code]                      16.960
    
                                 JNIEnv_::CallStaticVoidMethod         test                                0
    
                                 main                                  test                                0
    
                                 __libc_start_main                     libc-2.12.so                        0

    Optionally, you can attach to the process that calls the Java method, e.g.:

    $ ./test &
    [1] 20945
    $ amplxe-cl -collect advanced-hotspots -knob collection-detail=stack-and-callcount -mrte-mode=auto -target-pid 20945
    $ amplxe-cl -R callstacks
    amplxe: Using result path `/home/peter/JNI/r001ah'
    amplxe: Executing actions 75 % Generating a report                             
    Function                            Function Stack                            CPU Time  Module              Function (Full)                                                                            Source File  Start Address     
    ----------------------------------  ----------------------------------------  --------  ------------------  -----------------------------------------------------------------------------------------  -----------  ------------------
    jni_CallStaticVoidMethodV                                                     105.895s  libjvm.so           jni_CallStaticVoidMethodV                                                                  [Unknown]    0x570b30          
                                        JNIEnv_::CallStaticVoidMethod             105.895s  test                JNIEnv_::CallStaticVoidMethod(_jclass*, _jmethodID*, ellipsis)                             jni.h        0x400958          
                                        main                                            0s  test                main                                                                                       test.cpp     0x400744          
                                        __libc_start_main                               0s  libc-2.12.so        __libc_start_main                                                                          [Unknown]    0x3845a1ec60      
                                        _start                                          0s  test                _start                                                                                     [Unknown]    0x400660         
    
    

     

For more complete information about compiler optimizations, see our Optimization Notice.