
io.opentelemetry.javaagent.tooling.bytebuddy.ExceptionHandlers Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of opentelemetry-javaagent-tooling Show documentation
Show all versions of opentelemetry-javaagent-tooling Show documentation
Instrumentation of Java libraries using OpenTelemetry.
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.tooling.bytebuddy;
import io.opentelemetry.javaagent.bootstrap.ExceptionLogger;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.asm.Advice.ExceptionHandler;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.bytecode.StackManipulation;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public final class ExceptionHandlers {
// Bootstrap ExceptionLogger.class will always be resolvable, so we'll use it in the log name
private static final String LOGGER_NAME = ExceptionLogger.class.getName().replace('.', '/');
private static final ExceptionHandler EXCEPTION_STACK_HANDLER =
new ExceptionHandler.Simple(
new StackManipulation() {
// Pops one Throwable off the stack. Maxes the stack to at least 2 (throwable, string).
private final StackManipulation.Size size = new StackManipulation.Size(-1, 2);
@Override
public boolean isValid() {
return true;
}
@Override
public StackManipulation.Size apply(MethodVisitor mv, Implementation.Context context) {
String name = context.getInstrumentedType().getName();
// writes the following bytecode:
// try {
// ExceptionLogger.logSuppressedError("exception in instrumentation", t);
// } catch (Throwable t2) {
// }
Label logStart = new Label();
Label logEnd = new Label();
Label eatException = new Label();
Label handlerExit = new Label();
// Frames are only meaningful for class files in version 6 or later.
boolean frames = context.getClassFileVersion().isAtLeast(ClassFileVersion.JAVA_V6);
mv.visitTryCatchBlock(logStart, logEnd, eatException, "java/lang/Throwable");
// stack: (top) throwable
mv.visitLabel(logStart);
mv.visitLdcInsn("Failed to handle exception in instrumentation for " + name);
mv.visitInsn(Opcodes.SWAP); // stack: (top) throwable,string
mv.visitMethodInsn(
Opcodes.INVOKESTATIC,
LOGGER_NAME,
"logSuppressedError",
"(Ljava/lang/String;Ljava/lang/Throwable;)V",
/* isInterface= */ false);
mv.visitLabel(logEnd);
mv.visitJumpInsn(Opcodes.GOTO, handlerExit);
// if the runtime can't reach our ExceptionLogger,
// silently eat the exception
mv.visitLabel(eatException);
if (frames) {
mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/Throwable"});
}
mv.visitInsn(Opcodes.POP);
// mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable",
// "printStackTrace", "()V", false);
mv.visitLabel(handlerExit);
if (frames) {
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
// there may be at most one frame at given code location, we need to add an extra
// NOP instruction to ensure that there isn't a duplicate frame
mv.visitInsn(Opcodes.NOP);
}
return size;
}
});
public static ExceptionHandler defaultExceptionHandler() {
return EXCEPTION_STACK_HANDLER;
}
private ExceptionHandlers() {}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy