Skip to content

Instantly share code, notes, and snippets.

@vladimir-bukhtoyarov
Last active December 12, 2019 13:39
Show Gist options
  • Save vladimir-bukhtoyarov/2d3c0f1cdda0a9d6bd8596f4df323add to your computer and use it in GitHub Desktop.
Save vladimir-bukhtoyarov/2d3c0f1cdda0a9d6bd8596f4df323add to your computer and use it in GitHub Desktop.
Profiler for detecting new thread creation
package com.ringcentral.tread_creation_profiler;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassInjector;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.utility.JavaModule;
import java.io.File;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Constructor;
import java.nio.file.Files;
import java.util.Collections;
import java.util.UUID;
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
public class ThreadCreationAgent {
public static void main(String[] args) throws Exception {
premain(null, ByteBuddyAgent.install());
playWithThreads();
}
public static void premain(String arg, Instrumentation inst) throws Exception {
File temp = Files.createTempDirectory("tmp").toFile();
ClassInjector.UsingInstrumentation.of(temp, ClassInjector.UsingInstrumentation.Target.BOOTSTRAP, ByteBuddyAgent.getInstrumentation())
.inject(Collections.singletonMap(
new TypeDescription.ForLoadedType(MyConstructorInterceptor.class),
ClassFileLocator.ForClassLoader.read(MyConstructorInterceptor.class).resolve())
);
new AgentBuilder.Default()
.ignore(ElementMatchers.nameStartsWith("net.bytebuddy."))
.with(AgentBuilder.Listener.StreamWriting.toSystemOut())
.enableBootstrapInjection(ByteBuddyAgent.getInstrumentation(), temp)
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.type(ElementMatchers.named("java.lang.Thread"))
.transform(
new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {
return builder.visit(Advice.to(MyConstructorInterceptor.class).on(isConstructor()));
}
}
)
.installOn(inst);
}
public static class MyConstructorInterceptor {
@Advice.OnMethodEnter
public static void enter(@Advice.Origin Constructor method) {
RuntimeException stacktrace = new RuntimeException("New thread created");
stacktrace.printStackTrace(System.err);
}
}
private static void playWithThreads() {
while (true) {
try {
Thread.sleep(3000);
String threadName = UUID.randomUUID().toString();
Runnable runnable = () -> System.out.println("Hello + from thread " + Thread.currentThread().getName());
Thread thread = new Thread(runnable, threadName);
thread.start();
} catch (InterruptedException e) {
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment