JFR can record two types of exception events, "jdk.JavaExceptionThrow" which is emitted when a java.lang.Exception object (or subclass) is created and "jdk.JavaErrorThrow" when a java.lang.Error object (or subclass) is allocated.
The split was made so "jdk.JavaErrorThrow" could be enabled by default. Earlier version of JFR only supported a fixed number of options (enabled, stackTrace, threshold and period) and an event for every exception would have lead to increased overhead and buffers being flushed too quickly. Applications where catching exceptions are part of program flow would be especially problematic, for example:
void parseInteger(String text, int defaultValue) {
try {
return Integer.parseInt(text);
} catch (NumberFormatException nfe) {
return defaultValue;
}
}
One idea is to limit the number of exception using the new "rate" option introduced in JDK 16. An upper limit of 300 events per second could be set. This would allow the exception profiler to be always on. A drawback of this approach is that 299 of 300 events might be NumberFormatException, so other interesting exceptions would be lost.
To prevent this, a second idea is to ignore an exception class when more than 30 events/second of that type have been emitted. A drawback of this approach is that the same exception class could be used at multiple places, for example NullPointerException, ClassCastException or IllegalArgumentException. It might also skew the statistical properties of the result.
A third approach is to ignore an exception class if many objects of that type are allocated at the same call site. Since creating exceptions can be expensive (the JVM must fill in the stack trace), it could make sense to create an event type that tells users about those locations. For example:
jdk.ExceptionHotspot {
startTime = 10:51:43.051 (2022-07-30)
exceptions = 6736/s
type = java.lang.NullPointerException
location = com.example.FooBar.baz(int, String) line: 43
}
It might be possible to piggyback on the existing mechanism in the JVM that fills in the stack trace. When it walks the stack to create the stack trace, it ignores frames up to the constructor of the exception class, so the top frame becomes the call site where the exception object was allocated. This means JFR doesn't have to walk the frames and the overhead could be low.
One complication is that -XX:-StackTraceInThrowable could be specified, in which case the stack trace is not filled in. JFR could disable the profiler in those cases, or it could walk the stack and take the penalty. It would still be cheaper than running with StackTraceInThrowable enabled, which is the default today.
The split was made so "jdk.JavaErrorThrow" could be enabled by default. Earlier version of JFR only supported a fixed number of options (enabled, stackTrace, threshold and period) and an event for every exception would have lead to increased overhead and buffers being flushed too quickly. Applications where catching exceptions are part of program flow would be especially problematic, for example:
void parseInteger(String text, int defaultValue) {
try {
return Integer.parseInt(text);
} catch (NumberFormatException nfe) {
return defaultValue;
}
}
One idea is to limit the number of exception using the new "rate" option introduced in JDK 16. An upper limit of 300 events per second could be set. This would allow the exception profiler to be always on. A drawback of this approach is that 299 of 300 events might be NumberFormatException, so other interesting exceptions would be lost.
To prevent this, a second idea is to ignore an exception class when more than 30 events/second of that type have been emitted. A drawback of this approach is that the same exception class could be used at multiple places, for example NullPointerException, ClassCastException or IllegalArgumentException. It might also skew the statistical properties of the result.
A third approach is to ignore an exception class if many objects of that type are allocated at the same call site. Since creating exceptions can be expensive (the JVM must fill in the stack trace), it could make sense to create an event type that tells users about those locations. For example:
jdk.ExceptionHotspot {
startTime = 10:51:43.051 (2022-07-30)
exceptions = 6736/s
type = java.lang.NullPointerException
location = com.example.FooBar.baz(int, String) line: 43
}
It might be possible to piggyback on the existing mechanism in the JVM that fills in the stack trace. When it walks the stack to create the stack trace, it ignores frames up to the constructor of the exception class, so the top frame becomes the call site where the exception object was allocated. This means JFR doesn't have to walk the frames and the overhead could be low.
One complication is that -XX:-StackTraceInThrowable could be specified, in which case the stack trace is not filled in. JFR could disable the profiler in those cases, or it could walk the stack and take the penalty. It would still be cheaper than running with StackTraceInThrowable enabled, which is the default today.