Reputation: 3171
I am trying to understand how Java Flight Recorder samples an application which use a native library (through JNA in my case).
Lets write a test case which will spend most of its time in native land:
public class Main {
interface MyLib extends Library {
long doStuff(long seed);
}
public static void main(String[] args) {
MyLib myLib = (MyLib) Native.loadLibrary("mylib", MyLib.class);
LongStream.range(0, 10)
.map(myLib::doStuff)
.forEach(System.out::println);
}
}
doStuff being a slow, cpu bound, function
int64_t doStuff(int64_t acc) {
for (int i = 0; i < 1<<30; i++) { acc += i; }
return acc;
}
doStuff takes ~2s to execute on my machine and main completes in ~30s. I run this test case with jdk1.8.0_60 using the following JVM options: -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=defaultrecording=true,dumponexit=true,dumponexitpath=jna.jfr
.
When I open jna.jfr
I see that the dump contains a single stack trace event. As I understand it, and unlike most profiler, JFR does not generate stack trace events when native code is running. I perfectly understand that JFR does not profile native code but I had expect stack trace events being generated with a stack trace truncated at java/native code boundary.
Is something wrong with my setup or is it the expected behavior ? I find it really error prone. If you don't carefully verify the sample count, it is so easy to believe that hotspots are in Java code while most of the time is spent in native code.
It is also impossible to know where are the most expensive native calls which is why you use a profiler in the first place :)
Upvotes: 0
Views: 971
Reputation: 7069
The Flight Recorder sampler only emits events when in Java. It would be possible to look at the last Java frame, if the sampler hits native code, but that's not how it is implemented.
Upvotes: 1