Article <Java support is back in VTune™ Amplifier XE> informs that VTune(TM) Amplifier XE 2013 already supports Java application, and Attaching to Java* processes for hardware event-based sampling is supported since VTune™ Amplifier XE 2013 Update 4.
The problem is that Java class may not be used directly in application. For example, Java application may work with Apache, Tomcat, Php and Mysql, etc. Sometime C/C++ code may call Java methods from class via JNI (Java Native Interface). This article educate to use JNI and how VTune Amplifier collects performance in Java class by JNI mode.
Steps:
1. Create a simple Java class, which has "calc" public method. See attached Demo.java file
2. Use Oracle* JDK 1.7 to compile Demo.java with "-g" option (generate symbol info in class file)
# ../../jdk1.7.0_11/bin/javac -g Demo.java
3. Run Demo class directly
# ../../jdk1.7.0_11/bin/java Demo
Note that “main” public method calls "calc" method in this case.
4. One important thing to be noted here is to specify the function signatures while obtaining the method IDs. To obtain the correct method signature, you can use the following Java comman:
# ../../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 (see attached), which uses the signature of method "calc"
6. Compile C++ file to generate executable
g++ -g test.cpp -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 -o test
7. Run C++ binary which calls public method “calc” from Demo class
First, you need to add 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
Then run "./test"
8. Now we can profile “calc” java method called by C++ built “test” application
# amplxe-cl -collect hotspots -mrte-mode=auto –duration 20 -- ./test
# amplxe-cl -report callstacks -r r000hs
# amplxe-cl -report callstacksamplxe: Using result path `/home/peter/jni_java/r003hs'
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
9. Also you can attach the process which runs Java method
# ./test &
[1] 16801
# amplxe-cl -collect lightweight-hotspots -knob enable-stack-collection=true -knob enable-call-counts=true -mrte-mode=auto -target-pid 16801
# amplxe-cl -report callstacks
amplxe: Using result path `/home/peter/jni_java/r001lh'
amplxe: Executing actions 50 % Generating a report
Function Call Stack Module CPU Time:Self
----------------------------- ----------------------- ------------------ -------------
JNIEnv_::CallStaticVoidMethod test 20.023
main test 20.023
__libc_start_main libc-2.12.so 0
pthread_cond_timedwait libpthread-2.12.so 0.002
os::PlatformEvent::park libjvm.so 0.002
WatcherThread::run libjvm.so 0
java_start libjvm.so 0
start_thread libpthread-2.12.so 0
clone libc-2.12.so 0