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 tobuild/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 instrumentedjmcRuntimeJarPath
- 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