From 3a333d8df8a0344dc2b1389e07e8bffdaa5245d6 Mon Sep 17 00:00:00 2001 From: Ziyi Lin Date: Tue, 26 Nov 2024 18:42:34 +0800 Subject: [PATCH] report with method descriptor --- .../java/io/type/pollution/agent/Agent.java | 39 +++++++++++++++++++ .../type/pollution/agent/ByteBuddyUtils.java | 10 +++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/agent/src/main/java/io/type/pollution/agent/Agent.java b/agent/src/main/java/io/type/pollution/agent/Agent.java index 3d4d5f2..58af44c 100644 --- a/agent/src/main/java/io/type/pollution/agent/Agent.java +++ b/agent/src/main/java/io/type/pollution/agent/Agent.java @@ -12,15 +12,21 @@ import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.pool.TypePool; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.lang.instrument.Instrumentation; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; +import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Collection; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -39,6 +45,8 @@ public class Agent { private static final int TRACING_DELAY_SECS = Integer.getInteger("io.type.pollution.delay", 0); private static final Long REPORT_INTERVAL_SECS = Long.getLong("io.type.pollution.report.interval"); private static final boolean ENABLE_LAMBDA_INSTRUMENTATION = Boolean.getBoolean("io.type.pollution.lambda"); + private static final String EXPORT_AFFECTS_TO_FILE = System.getProperty("io.type.pollution.export"); + public static final boolean TRACE_WITH_DESC = EXPORT_AFFECTS_TO_FILE != null ? true : Boolean.getBoolean("io.type.pollution.trace.withdesc"); public static void premain(String agentArgs, Instrumentation inst) { if (ENABLE_FULL_STACK_TRACES) { @@ -167,6 +175,9 @@ private static void printReport(boolean last) { summary.append("Date:\t").append(REPORT_TIMESTAMP.format(LocalDateTime.now())).append('\n'); summary.append("Last:\t").append(last).append('\n'); CharSequence typePollutionReport = reportOf(TraceInstanceOf.orderedTypePollutionCountersSnapshot(TYPE_UPDATE_COUNT_MIN)); + if (EXPORT_AFFECTS_TO_FILE != null) { + exportAffectedMethods(TraceInstanceOf.orderedTypePollutionCountersSnapshot(TYPE_UPDATE_COUNT_MIN)); + } if (typePollutionReport.length() > 0) { summary.append("--------------------------\nType Pollution:\n"); summary.append(typePollutionReport); @@ -223,6 +234,34 @@ private static void printReport(boolean last) { } } + private static void exportAffectedMethods(Collection counters) { + if (counters.isEmpty()) { + return; + } + Set affectedMethods = new HashSet<>(); + StringBuilder sb = new StringBuilder(); + for (TraceInstanceOf.TraceCounter.Snapshot counter : counters) { + for (TraceInstanceOf.TraceCounter.Snapshot.TraceSnapshot stack : counter.traces) { + String[] traceContents = stack.trace.split("--"); + if (affectedMethods.add(traceContents[0])) { + sb.append(traceContents[0]).append("\n"); + } + } + } + long pid = ProcessHandle.current().pid(); + String fileName = EXPORT_AFFECTS_TO_FILE; + File file = new File(fileName); + if (file.exists()) { + fileName = fileName + "-" + pid + ".txt"; + } + try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) { + writer.write(sb.toString()); + System.out.println("Affected methods are dumped to " + fileName); + } catch (IOException e) { + e.printStackTrace(); + } + } + private static boolean closeDump() { try { DUMP.close(); diff --git a/agent/src/main/java/io/type/pollution/agent/ByteBuddyUtils.java b/agent/src/main/java/io/type/pollution/agent/ByteBuddyUtils.java index 0611fc0..04c3101 100644 --- a/agent/src/main/java/io/type/pollution/agent/ByteBuddyUtils.java +++ b/agent/src/main/java/io/type/pollution/agent/ByteBuddyUtils.java @@ -5,6 +5,8 @@ import net.bytebuddy.jar.asm.Opcodes; import net.bytebuddy.jar.asm.Type; +import static io.type.pollution.agent.Agent.TRACE_WITH_DESC; + public class ByteBuddyUtils { static class ByteBuddyTypePollutionInstructionAdapter extends net.bytebuddy.jar.asm.MethodVisitor { @@ -13,21 +15,23 @@ static class ByteBuddyTypePollutionInstructionAdapter extends net.bytebuddy.jar. private final String methodName; private final String classFile; + private final String desc; private String tracePrefix; private int line; - protected ByteBuddyTypePollutionInstructionAdapter(int api, net.bytebuddy.jar.asm.MethodVisitor methodVisitor, String classDescriptor, String methodName, String classFile) { + protected ByteBuddyTypePollutionInstructionAdapter(int api, net.bytebuddy.jar.asm.MethodVisitor methodVisitor, String classDescriptor, String methodName, String classFile, String desc) { super(api, methodVisitor); this.classDescriptor = classDescriptor; this.methodName = methodName; this.classFile = classFile; + this.desc = desc; } private String trace() { if (tracePrefix == null) { - tracePrefix = classDescriptor.replace('/', '.') + "." + methodName + "(" + (classFile != null ? classFile : "Unknown Source)"); + tracePrefix = classDescriptor.replace('/', '.') + "." + methodName + (TRACE_WITH_DESC ? desc + "--" : "") + "(" + (classFile != null ? classFile : "Unknown Source)"); } if (classFile != null) { return tracePrefix + ":" + line + ")"; @@ -139,7 +143,7 @@ public void visit(final int version, final int access, final String name, final public net.bytebuddy.jar.asm.MethodVisitor visitMethod(int flags, String name, String desc, String signature, String[] exceptions) { return new ByteBuddyTypePollutionInstructionAdapter(api, super.visitMethod(flags, name, desc, - signature, exceptions), this.name, name, source); + signature, exceptions), this.name, name, source, desc); } } }