EventHandlers can be instrumented via the EventHandlerCreator where a write method is built via call to:
buildWriteMethod()
In this code, a try catch handler is built with a call to eventWriter.reset(), a private method.
mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/Throwable"});
visitMethod(mv, Opcodes.INVOKESTATIC, TYPE_EVENT_WRITER, METHOD_GET_EVENT_WRITER);
// stack: [ex] [BW]
mv.visitInsn(Opcodes.DUP);
// stack: [ex] [BW] [BW]
Label rethrow = new Label();
mv.visitJumpInsn(Opcodes.IFNULL, rethrow);
// stack: [ex] [BW]
mv.visitInsn(Opcodes.DUP);
// stack: [ex] [BW] [BW]
visitMethod(mv, Opcodes.INVOKEVIRTUAL, TYPE_EVENT_WRITER, METHOD_RESET);
EventWriter.java has:
private void reset() {
This code does not run unless an exception is somehow thrown. As a test, I modified the beginEvent code to throw an exception in the middle of it's execution with:
Random r = new Random();
int i = r.nextInt(2);
if (i == 1) {
throw new Exception("beginEvent");
}
The result when running this is:
Exception in thread "main" java.lang.IllegalAccessError: class jdk.jfr.internal.handlers.EventHandler1679_1608150785512-126103 tried to access private method 'void jdk.jfr.internal.EventWriter.reset()' (jdk.jfr.internal.handlers.EventHandler1679_1608150785512-126103 and jdk.jfr.internal.EventWriter are in module jdk.jfr of loader 'bootstrap')
at jdk.jfr/jdk.jfr.internal.handlers.EventHandler1679_1608150785512-126103.write(Unknown Source)
at com.redhat.jfr.events.StringEvent.commit(StringEvent.java)
at com.redhat.jfr.tests.recording.TestConsecutiveRecordings.main(TestConsecutiveRecordings.java:22)
I'm not yet sure how to reach this code path in practice though, so I'll have to read the code some more to construct a reproducer.
buildWriteMethod()
In this code, a try catch handler is built with a call to eventWriter.reset(), a private method.
mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/Throwable"});
visitMethod(mv, Opcodes.INVOKESTATIC, TYPE_EVENT_WRITER, METHOD_GET_EVENT_WRITER);
// stack: [ex] [BW]
mv.visitInsn(Opcodes.DUP);
// stack: [ex] [BW] [BW]
Label rethrow = new Label();
mv.visitJumpInsn(Opcodes.IFNULL, rethrow);
// stack: [ex] [BW]
mv.visitInsn(Opcodes.DUP);
// stack: [ex] [BW] [BW]
visitMethod(mv, Opcodes.INVOKEVIRTUAL, TYPE_EVENT_WRITER, METHOD_RESET);
EventWriter.java has:
private void reset() {
This code does not run unless an exception is somehow thrown. As a test, I modified the beginEvent code to throw an exception in the middle of it's execution with:
Random r = new Random();
int i = r.nextInt(2);
if (i == 1) {
throw new Exception("beginEvent");
}
The result when running this is:
Exception in thread "main" java.lang.IllegalAccessError: class jdk.jfr.internal.handlers.EventHandler1679_1608150785512-126103 tried to access private method 'void jdk.jfr.internal.EventWriter.reset()' (jdk.jfr.internal.handlers.EventHandler1679_1608150785512-126103 and jdk.jfr.internal.EventWriter are in module jdk.jfr of loader 'bootstrap')
at jdk.jfr/jdk.jfr.internal.handlers.EventHandler1679_1608150785512-126103.write(Unknown Source)
at com.redhat.jfr.events.StringEvent.commit(StringEvent.java)
at com.redhat.jfr.tests.recording.TestConsecutiveRecordings.main(TestConsecutiveRecordings.java:22)
I'm not yet sure how to reach this code path in practice though, so I'll have to read the code some more to construct a reproducer.