private static synchronized void initInstrumentation()

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();
                }
            });
        }
    }