for readability better making I am
This commit is contained in:
parent
f275d0de62
commit
862aad4462
3 changed files with 42 additions and 39 deletions
|
|
@ -1,9 +1,6 @@
|
|||
package com.github.shautvast.exceptional;
|
||||
|
||||
import java.lang.classfile.ClassElement;
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.ClassModel;
|
||||
import java.lang.classfile.MethodModel;
|
||||
import java.lang.classfile.*;
|
||||
import java.lang.classfile.instruction.ReturnInstruction;
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.constant.MethodTypeDesc;
|
||||
|
|
@ -21,6 +18,7 @@ public class Agent {
|
|||
private static final String MESSAGE = "--- Exceptional agent active";
|
||||
|
||||
public static void premain(String agentArgs, Instrumentation instrumentation) throws Exception {
|
||||
// add transformer
|
||||
instrumentation.addTransformer(new ClassFileTransformer() {
|
||||
@Override
|
||||
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
|
||||
|
|
@ -33,34 +31,45 @@ public class Agent {
|
|||
}
|
||||
}, true);
|
||||
|
||||
// we only want to redefine Throwable
|
||||
byte[] bytecode = Files.readAllBytes(
|
||||
Path.of(Agent.class.getResource("/java/lang/Throwable.class").toURI()));
|
||||
|
||||
instrumentation.redefineClasses(new ClassDefinition(Throwable.class, bytecode));
|
||||
}
|
||||
|
||||
private static byte[] instrumentThrowable(String className, byte[] classfileBuffer) {
|
||||
private static byte[] instrumentThrowable(String className, byte[] bytecode) {
|
||||
// we only want to instrument Throwable
|
||||
// or rather,,, is this the right way? This way we also intercept new any Exception that is not thrown
|
||||
// But,,, who does that?? (famous last words)
|
||||
if (className.equals("java/lang/Throwable")) {
|
||||
ClassFile classFile = ClassFile.of();
|
||||
ClassModel classModel = classFile.parse(classfileBuffer);
|
||||
return instrumentByteCode(classFile, classModel);
|
||||
ClassModel classModel = classFile.parse(bytecode);
|
||||
return instrumentConstructors(classFile, classModel);
|
||||
} else {
|
||||
return classfileBuffer;
|
||||
return bytecode;
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] instrumentByteCode(ClassFile classFile, ClassModel classModel) {
|
||||
private static byte[] instrumentConstructors(ClassFile classFile, ClassModel classModel) {
|
||||
return classFile.build(classModel.thisClass().asSymbol(), classBuilder -> {
|
||||
for (ClassElement ce : classModel) {
|
||||
if (ce instanceof MethodModel mm) {
|
||||
if (mm.methodName().toString().equals("<init>")) {
|
||||
if (ce instanceof MethodModel mm && mm.methodName().toString().equals("<init>")) {
|
||||
instrumentMethodWithMyExceptionLogger(classBuilder, mm);
|
||||
continue;
|
||||
}
|
||||
classBuilder.with(ce);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void instrumentMethodWithMyExceptionLogger(ClassBuilder classBuilder, MethodModel mm) {
|
||||
classBuilder.withMethod(mm.methodName(), mm.methodType(), mm.flags().flagsMask(),
|
||||
methodBuilder ->
|
||||
methodBuilder.transformCode(mm.code().get(), ((builder, element) -> {
|
||||
if (element instanceof ReturnInstruction) {
|
||||
builder.aload(0);
|
||||
builder.invokestatic(
|
||||
ClassDesc.of("com.github.shautvast.exceptional.ThrowableHandler"), "handle",
|
||||
builder.aload(0); // load `this` on the stack, ie the Throwable instance
|
||||
builder.invokestatic( // call my code
|
||||
ClassDesc.of("com.github.shautvast.exceptional.ExceptionLogger"), "log",
|
||||
MethodTypeDesc.ofDescriptor("(Ljava/lang/Throwable;)V"));
|
||||
builder.return_();
|
||||
} else {
|
||||
|
|
@ -68,11 +77,5 @@ public class Agent {
|
|||
}
|
||||
})
|
||||
));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
classBuilder.with(ce);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.github.shautvast.exceptional;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@SuppressWarnings("unused") // this code is called from the instrumented code
|
||||
public class ExceptionLogger {
|
||||
public static void log(Throwable throwable) {
|
||||
System.out.print("Logging exception:");
|
||||
Arrays.stream(throwable.getStackTrace()).forEach(System.out::println);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
package com.github.shautvast.exceptional;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ThrowableHandler {
|
||||
public static void handle(Throwable throwable) {
|
||||
System.out.print("Handling exception:");
|
||||
Arrays.stream(throwable.getStackTrace()).forEach(System.out::println);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue