opentelemetry-java-instrume.../docs/contributing/javaagent-jar-components.md

3.2 KiB

Understanding the javaagent components

OpenTelemetry Auto Instrumentation java agent's jar can logically be divided into 3 parts.

opentelemetry-javaagent module

This module consists of single class io.opentelemetry.auto.bootstrap.AgentBootstrap which implements Java instrumentation agent. 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 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, calledinst. 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 opentelemetry-javaagent/build/libs/opentelemetry-javaagent-<version>-all.jar, you will see the following "clusters" of classes:

  • inst/ - contains agent-tooling module and instrumentation submodules, loaded and isolated inside AgentClassLoader. Including OpenTelemetry SDK (and the built-in exporters when using the -all artifact).
  • 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 javaagent jar file by Shadow Gradle plugin.