Instrumentation

Bytecode Instrumentation #

The goal of the instrumentation is to insert yield points in the target program. JMC achieves this goal using a Java agent that transforms classes as they are loaded. The transformation ensures that traditional concurrent primitives used within the target program are replaced with JMC defined concurrent primitives. The JMC concurrent primitives are programmed to interact specifically with the JMC runtime to pass events and yield control whenever necessary.

Here is a concrete example of the transformation that the JMC Java agent performs. The following user program

public class CounterIncrementer extends Thread {
    Counter counter;
    ReentrantLock lock;

    ...

    @Override
    public void run() {
        try {
            lock.lock();
            counter.inc();
        } finally {
            lock.unlock();
        }
    }
}

is transformed into

public class CounterIncrementer extends JmcThread {
    Counter counter;
    JmcReentrantLock lock;

    ...

    @Override
    public void run1() {
        try {
            lock.lock();
            counter.inc();
        } finally {
            lock.unlock();
        }
    }
}

Specifically, Thread is replaced with JmcThread and ReentrantLock is replaced with JmcReentrantLock. Both JMC counterparts yield control to the JMC runtime when the thread is created, started, when the lock is acquired or release, etc.

Agent #

The agent is defined in the agent sub-project of the main JMC repo. Starting from the InstrumentationAgent.java file, the agent instruments classes using the ASM library. The concurrent primitives currently supported are documented here.

The agent accepts a few parameters that are passed as arguments with the -javaagent JVM flag.

  • debug - enables logging of the instrumented classes.
  • debugSavePath - the path to store the instrumented classes. Defaults to build/generated/instrumented
  • instrumentingPackages - a semi-colon separated list of package prefixes that defines the scope of the instrumentation. Only classes whose package name matches any one of the prefixes specified will be instrumented.
  • excludedPackages - a semi-colon separated list of package prefixes to exclude. Classes whose package name matches any in the list will not be instrumented
  • jmcRuntimeJarPath - the path to the JMC library Jar. The classes in the JMC library jar will be loaded first to ensure instrumentation is successful. Defaults to /lib/jmc-<version>.jar

The agent invokes different ASM visitors sequentially to instrument different concurrent primitives within the Java JDK. A comprehensive list of supported primitives is listed here