Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Instrumenting JVM Thread Creation with Java Agents

Tech 1

Setting Up the Instrumentation Agent

To capture thread creation events at the JVM level, implement a premain method that registers a class transformer during the agent initializatoin phase.

import java.lang.instrument.Instrumentation;

public class ThreadAuditAgent {
    public static void premain(String args, Instrumentation instrumentation) {
        instrumentation.addTransformer(new ThreadSpawnInterceptor());
    }
}

Intercepting Thread Class Loading

The transformer intercepts class bytes as they load into the JVM. Target the java.lang.Thread class to instrument its constructors or the start() method.

import java.lang.instrument.ClassFileTransformer;
import java.security.ProtectionDomain;
import javassist.*;

public class ThreadSpawnInterceptor implements ClassFileTransformer {
    
    @Override
    public byte[] transform(ClassLoader loader, String className, 
                           Class<?> classBeingRedefined,
                           ProtectionDomain protectionDomain, 
                           byte[] classfileBuffer) {
        
        if (!"java/lang/Thread".equals(className)) {
            return classfileBuffer;
        }
        
        try {
            ClassPool pool = ClassPool.getDefault();
            CtClass clazz = pool.get("java.lang.Thread");
            
            CtConstructor[] constructors = clazz.getDeclaredConstructors();
            for (CtConstructor constructor : constructors) {
                constructor.insertAfter(
                    "System.out.println(\"[AUDIT] Thread created: \" + this.getName());"
                );
            }
            
            return clazz.toBytecode();
        } catch (Exception e) {
            e.printStackTrace();
            return classfileBuffer;
        }
    }
}

Sample Application with Thread Pool

Demonstrate the monitoring with a concurrent application spawning multiple worker threads.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ConcurrentTaskDriver {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(4);
        
        for (int i = 0; i < 10; i++) {
            final int taskId = i;
            executor.submit(() -> {
                System.out.println("Executing task " + taskId + 
                                 " in " + Thread.currentThread().getName());
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }
        
        executor.shutdown();
    }
}

Agent Lifecycle Management

Attach a shutdown hook to ensure the instrumentation agent releases resources when the JVM terminates.

public class ThreadAuditAgent {
    private static volatile Instrumentation globalInstrumentation;
    
    public static void premain(String args, Instrumentation inst) {
        globalInstrumentation = inst;
        inst.addTransformer(new ThreadSpawnInterceptor());
        
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("[AUDIT] Terminating thread monitoring agent");
            // Perform cleanup: close file handles, flush buffers
        }));
    }
    
    public static Instrumentation getInstrumentation() {
        return globalInstrumentation;
    }
}

Configure the agent manifest in META-INF/MANIFEST.MF:

Premain-Class: ThreadAuditAgent
Can-Redefine-Classes: true
Can-Retransform-Classes: true

Launch with the agent attached:

java -javaagent:thread-audit.jar -jar target-application.jar

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.