From 67766fd13b91347dcc5ccdc27590e5433f2e67c2 Mon Sep 17 00:00:00 2001 From: Nikita Salnikov-Tarnovski Date: Wed, 6 May 2020 20:28:35 +0300 Subject: [PATCH] Add documentation about java agent structure and related classloaders (#380) --- CONTRIBUTING.md | 47 +++++++++++++++++++ .../opentelemetry/auto/bootstrap/Agent.java | 3 +- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f23f0a974b..4a09a5772a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,6 +8,53 @@ In order to fully build and test this whole repository you need the following: * Java 8 should be set as default: `java -version` should give you version 8. * Defined environment variables `JAVA_8_HOME` and `JAVA_9_HOME` which point to the corresponding java homes. +### Plugin structure +OpenTelemetry Auto Instrumentation java agent's jar can logically be divided into 3 parts. + +#### `java-agent` module +This module consists of single class `io.opentelemetry.auto.bootstrap.AgentBootstrap` +which implements [Java instrumentation agent](https://docs.oracle.com/javase/7/docs/api/java/lang/instrument/package-summary.html). +This class is loaded during application startup by application classloader. +Its sole responsibility is to push agent's classes into JVM's bootstrap classloader +and immediately delegate to `io.opentelemetry.auto.bootstrap.Agent` (now in the bootstrap class loader) class from there. + +#### `agent-bootstrap` module +This module contains support classes for actual instrumentations to be loaded later and separately. +These classes should be available from all possible classloaders in the running application. +For this reason `java-agent` puts all these classes into JVM's bootstrap classloader. +For the same reason this module should be as small as possible and have as few dependencies as possible. +Otherwise, there is a risk of accidentally exposing this classes to the actual application. + +#### `agent-tooling` module and `instrumentation` submodules +Contains everything necessary to make instrumentation machinery work, +including integration with [ByteBuddy](https://bytebuddy.net/) and actual library-specific instrumentations. +As these classes depend on many classes from different libraries, +it is paramount to hide all these classes from the host application. +This is achieved in the following way: +* When `java-agent` module builds the final agent, it moves all classes from `instrumentation` submodules +and `agent-tooling` module into a separate folder inside final jar file, called `auto-tooling-and-instrumentation.isolated`. +In addition, the extension of all class files is changed from `class` to `classdata`. +This ensures that general classloaders cannot find nor load these classes. +* When `io.opentelemetry.auto.bootstrap.Agent` starts up, +it creates an instance of `io.opentelemetry.auto.bootstrap.AgentClassLoader`, +loads an `io.opentelemetry.auto.tooling.AgentInstaller` from that `AgentClassLoader` +and then passes control on to the `AgentInstaller` (now in the `AgentClassLoader`). The `AgentInstaller` then installs all of the instrumentations with the help of ByteBuddy. + +The complicated process above ensures that the majority of auto-instrumentation agent's classes +are totally isolated from application classes, +and an instrumented class from arbitrary classloader in JVM can still access helper classes from bootstrap classloader. + +#### Agent jar structure +If you now look inside `java-agent/build/libs/opentelemetry-auto-.jar`, +you will see the following "clusters" of classes: +* `auto-tooling-and-instrumentation.isolated/` - contains `agent-tooling` module and +`instrumentation` submodules, loaded and isolated inside `AgentClassLoader`. +Including OpenTelemetry SDK. +* `io/opentelemetry/auto/bootstrap/` - contains `agent-bootstrap` module and available in +bootstrap classloader. +* `io/opentelemetry/auto/shaded/` - contains OpenTelemetry API and its dependencies. +Shaded during creation of `java-agent` jar file by Shadow Gradle plugin. + ### Testing #### Java versions Open Telemetry Auto Instrumentation's minimal supported version is java 7. diff --git a/agent-bootstrap/src/main/java/io/opentelemetry/auto/bootstrap/Agent.java b/agent-bootstrap/src/main/java/io/opentelemetry/auto/bootstrap/Agent.java index aee37e9c11..c40fcb5837 100644 --- a/agent-bootstrap/src/main/java/io/opentelemetry/auto/bootstrap/Agent.java +++ b/agent-bootstrap/src/main/java/io/opentelemetry/auto/bootstrap/Agent.java @@ -197,12 +197,11 @@ public class Agent { } /** - * Create the agent classloader. This must be called after the bootstrap jar has been appened to + * Create the agent classloader. This must be called after the bootstrap jar has been appended to * the bootstrap classpath. * * @param innerJarFilename Filename of internal jar to use for the classpath of the agent * classloader - * @param bootstrapURL * @return Agent Classloader */ private static ClassLoader createAgentClassLoader(