Sometimes, a Java agent may need to have the ability to detach or hot-update.
In this example, the WithCustomMapping#bootstrap
API is used for instrumentation, but once the target class is enhanced and the bootstrap method is executed,
the class loader for the agent cannot be unloaded. There are several known scenarios:
- If
inline=true
is used without using theWithCustomMapping#bootstrap
API, unloading can be performed normally. - If the
WithCustomMapping#bootstrap
API is used(-Dagent.indy.enabled=true
) but the target method is not called, i.e., the custom bootstrap method is not executed, unloading can be completed normally. - If the
WithCustomMapping#bootstrap
API is used(-Dagent.indy.enabled=true
) and the target method is called, i.e., the custom bootstrap method is executed, unloading cannot be completed normally.
The custom bootstrap method in this example mainly involves two classes: IndyBootstrapDispatcher
and IndyBootstrap
.
They are copied from the elastic-apm-agent and simplified. This implementation uses a class loader named IndyPluginClassLoader
, which inherits from ByteArrayClassLoader
, to load the custom advice class.
- build the project
mvn clean package
- To run this example using Java 8 (replace the
${JAVA_8_HOME}
and${BUILD_PATH}
)
${JAVA_8_HOME}/bin/java \
-javaagent:${BUILD_PATH}/agent/target/agent-1.0-SNAPSHOT.jar \
-Dagent.detach.file=${BUILD_PATH}/detach.txt \
-Dagent.file=${BUILD_PATH}/agent-core/target/agent-core-1.0-SNAPSHOT.jar \
-Dagent.indy.enabled=true \
-XX:+TraceClassUnloading \
-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses \
-Xms32M \
-Xmx32M \
-jar ${BUILD_PATH}/app/target/app-1.0-SNAPSHOT.jar
- Ensure that the custom bootstrap method is executed.
curl http://127.0.0.1:8080/
- Detach the javaagent(rename the
detach2.txt
todetach.txt
)
mv detach2.txt detach.txt