in apm-agent-core/src/main/java/co/elastic/apm/agent/bci/ElasticApmAgent.java [234:309]
private static synchronized void initInstrumentation(final ElasticApmTracer tracer, Instrumentation instrumentation,
Iterable<ElasticApmInstrumentation> instrumentations, boolean premain) {
CoreConfigurationImpl coreConfig = tracer.getConfig(CoreConfigurationImpl.class);
if (!coreConfig.isEnabled()) {
return;
}
ancientBytecodeInstrumentationEnabled = coreConfig.isInstrumentAncientBytecode();
String bytecodeDumpPath = coreConfig.getBytecodeDumpPath();
if (bytecodeDumpPath != null) {
bytecodeDumpPath = bytecodeDumpPath.trim();
if (!bytecodeDumpPath.isEmpty()) {
try {
File bytecodeDumpDir = Paths.get(bytecodeDumpPath).toFile();
if (!bytecodeDumpDir.exists()) {
bytecodeDumpDir.mkdirs();
}
System.setProperty("net.bytebuddy.dump", bytecodeDumpDir.getPath());
} catch (Exception e) {
SystemStandardOutputLogger.stdErrWarn("Failed to create directory to dump instrumented bytecode: " + e.getMessage());
}
}
}
final List<PluginClassLoaderRootPackageCustomizer> rootPackageCustomizers = DependencyInjectingServiceLoader.load(
PluginClassLoaderRootPackageCustomizer.class,
getAgentClassLoader());
for (PluginClassLoaderRootPackageCustomizer rootPackageCustomizer : rootPackageCustomizers) {
PluginClassLoaderCustomizations customizations = new PluginClassLoaderCustomizations(
rootPackageCustomizer.pluginClassLoaderRootPackages(),
rootPackageCustomizer.requiredModuleOpens()
);
PluginClassLoaderCustomizations previous = pluginPackages2pluginClassLoaderCustomizations.put(
rootPackageCustomizer.getPluginPackage(),
customizations
);
if (previous != null) {
throw new IllegalStateException("Only one PluginClassLoaderRootPackageCustomizer is allowed per plugin package: "
+ rootPackageCustomizer.getPluginPackage());
}
}
for (ElasticApmInstrumentation apmInstrumentation : instrumentations) {
mapInstrumentationCL2adviceClassName(
apmInstrumentation.getAdviceClassName(),
PrivilegedActionUtils.getClassLoader(apmInstrumentation.getClass()));
}
Runtime.getRuntime().addShutdownHook(new Thread(ThreadUtils.addElasticApmThreadPrefix("init-instrumentation-shutdown-hook")) {
@Override
public void run() {
tracer.stop();
}
});
Logger logger = getLogger();
if (ElasticApmAgent.instrumentation != null) {
logger.warn("Instrumentation has already been initialized");
return;
}
// POOL_ONLY because we don't want to cause eager linking on startup as the class path may not be complete yet
AgentBuilder agentBuilder = initAgentBuilder(tracer, instrumentation, instrumentations, logger, AgentBuilder.DescriptionStrategy.Default.POOL_ONLY, premain);
// Warmup Byte Buddy and agent's invokedynamic linkage paths on the attaching thread before installing it
if (tracer.getConfig(CoreConfigurationImpl.class).shouldWarmupByteBuddy()) {
agentBuilder = agentBuilder.with(new InstallationListenerImpl())
.warmUp(NonInstrumented.class)
.warmUp(Instrumented.class);
}
resettableClassFileTransformer = agentBuilder.installOn(ElasticApmAgent.instrumentation);
for (ConfigurationOption<?> instrumentationOption : coreConfig.getInstrumentationOptions()) {
//noinspection Convert2Lambda
instrumentationOption.addChangeListener(new ConfigurationOption.ChangeListener() {
@Override
public void onChange(ConfigurationOption configurationOption, Object oldValue, Object newValue) {
reInitInstrumentation();
}
});
}
}