Don't call Thread#setContextClassLoader() (#7391)
Related to #7220 Unfortunately it doesn't fix the aforementioned issue; while the CL used is no longer the agent classloader, gauge collection still throws that error. Still, I think this is a good change that removes one source of agent's CL leaking into application runtime.
This commit is contained in:
parent
9e5d9623c3
commit
c03bfc255b
|
@ -19,7 +19,6 @@ import io.opentelemetry.context.Scope;
|
|||
import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
|
||||
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;
|
||||
import io.opentelemetry.javaagent.bootstrap.AgentClassLoader;
|
||||
import io.opentelemetry.javaagent.bootstrap.AgentInitializer;
|
||||
import io.opentelemetry.javaagent.bootstrap.BootstrapPackagePrefixesHolder;
|
||||
import io.opentelemetry.javaagent.bootstrap.ClassFileTransformerHolder;
|
||||
import io.opentelemetry.javaagent.bootstrap.DefineClassHelper;
|
||||
|
@ -78,7 +77,7 @@ public class AgentInstaller {
|
|||
|
||||
private static final Map<String, List<Runnable>> CLASS_LOAD_CALLBACKS = new HashMap<>();
|
||||
|
||||
public static void installBytebuddyAgent(Instrumentation inst) {
|
||||
public static void installBytebuddyAgent(Instrumentation inst, ClassLoader extensionClassLoader) {
|
||||
addByteBuddyRawSetting();
|
||||
|
||||
Integer strictContextStressorMillis = Integer.getInteger(STRICT_CONTEXT_STRESSOR_MILLIS);
|
||||
|
@ -90,34 +89,37 @@ public class AgentInstaller {
|
|||
logVersionInfo();
|
||||
if (ConfigPropertiesUtil.getBoolean(JAVAAGENT_ENABLED_CONFIG, true)) {
|
||||
setupUnsafe(inst);
|
||||
List<AgentListener> agentListeners = loadOrdered(AgentListener.class);
|
||||
installBytebuddyAgent(inst, agentListeners);
|
||||
List<AgentListener> agentListeners = loadOrdered(AgentListener.class, extensionClassLoader);
|
||||
installBytebuddyAgent(inst, extensionClassLoader, agentListeners);
|
||||
} else {
|
||||
logger.fine("Tracing is disabled, not installing instrumentations.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void installBytebuddyAgent(
|
||||
Instrumentation inst, Iterable<AgentListener> agentListeners) {
|
||||
Instrumentation inst,
|
||||
ClassLoader extensionClassLoader,
|
||||
Iterable<AgentListener> agentListeners) {
|
||||
|
||||
WeakRefAsyncOperationEndStrategies.initialize();
|
||||
|
||||
EmbeddedInstrumentationProperties.setPropertiesLoader(
|
||||
AgentInitializer.getExtensionsClassLoader());
|
||||
EmbeddedInstrumentationProperties.setPropertiesLoader(extensionClassLoader);
|
||||
|
||||
setDefineClassHandler();
|
||||
|
||||
// If noop OpenTelemetry is enabled, autoConfiguredSdk will be null and AgentListeners are not
|
||||
// called
|
||||
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk = installOpenTelemetrySdk();
|
||||
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
|
||||
installOpenTelemetrySdk(extensionClassLoader);
|
||||
|
||||
ConfigProperties sdkConfig = autoConfiguredSdk.getConfig();
|
||||
InstrumentationConfig.internalInitializeConfig(new ConfigPropertiesBridge(sdkConfig));
|
||||
copyNecessaryConfigToSystemProperties(sdkConfig);
|
||||
|
||||
setBootstrapPackages(sdkConfig);
|
||||
setBootstrapPackages(sdkConfig, extensionClassLoader);
|
||||
|
||||
for (BeforeAgentListener agentListener : loadOrdered(BeforeAgentListener.class)) {
|
||||
for (BeforeAgentListener agentListener :
|
||||
loadOrdered(BeforeAgentListener.class, extensionClassLoader)) {
|
||||
agentListener.beforeAgent(autoConfiguredSdk);
|
||||
}
|
||||
|
||||
|
@ -140,7 +142,7 @@ public class AgentInstaller {
|
|||
agentBuilder = agentBuilder.with(new ExposeAgentBootstrapListener(inst));
|
||||
}
|
||||
|
||||
agentBuilder = configureIgnoredTypes(sdkConfig, agentBuilder);
|
||||
agentBuilder = configureIgnoredTypes(sdkConfig, extensionClassLoader, agentBuilder);
|
||||
|
||||
if (AgentConfig.isDebugModeEnabled(sdkConfig)) {
|
||||
agentBuilder =
|
||||
|
@ -152,7 +154,7 @@ public class AgentInstaller {
|
|||
}
|
||||
|
||||
int numberOfLoadedExtensions = 0;
|
||||
for (AgentExtension agentExtension : loadOrdered(AgentExtension.class)) {
|
||||
for (AgentExtension agentExtension : loadOrdered(AgentExtension.class, extensionClassLoader)) {
|
||||
if (logger.isLoggable(FINE)) {
|
||||
logger.log(
|
||||
FINE,
|
||||
|
@ -196,9 +198,11 @@ public class AgentInstaller {
|
|||
}
|
||||
}
|
||||
|
||||
private static void setBootstrapPackages(ConfigProperties config) {
|
||||
private static void setBootstrapPackages(
|
||||
ConfigProperties config, ClassLoader extensionClassLoader) {
|
||||
BootstrapPackagesBuilderImpl builder = new BootstrapPackagesBuilderImpl();
|
||||
for (BootstrapPackagesConfigurer configurer : load(BootstrapPackagesConfigurer.class)) {
|
||||
for (BootstrapPackagesConfigurer configurer :
|
||||
load(BootstrapPackagesConfigurer.class, extensionClassLoader)) {
|
||||
configurer.configure(builder, config);
|
||||
}
|
||||
BootstrapPackagePrefixesHolder.setBoostrapPackagePrefixes(builder.build());
|
||||
|
@ -209,9 +213,10 @@ public class AgentInstaller {
|
|||
}
|
||||
|
||||
private static AgentBuilder configureIgnoredTypes(
|
||||
ConfigProperties config, AgentBuilder agentBuilder) {
|
||||
ConfigProperties config, ClassLoader extensionClassLoader, AgentBuilder agentBuilder) {
|
||||
IgnoredTypesBuilderImpl builder = new IgnoredTypesBuilderImpl();
|
||||
for (IgnoredTypesConfigurer configurer : loadOrdered(IgnoredTypesConfigurer.class)) {
|
||||
for (IgnoredTypesConfigurer configurer :
|
||||
loadOrdered(IgnoredTypesConfigurer.class, extensionClassLoader)) {
|
||||
configurer.configure(builder, config);
|
||||
}
|
||||
|
||||
|
|
|
@ -62,18 +62,9 @@ public class AgentStarterImpl implements AgentStarter {
|
|||
@Override
|
||||
public void start() {
|
||||
extensionClassLoader = createExtensionClassLoader(getClass().getClassLoader(), javaagentFile);
|
||||
ClassLoader savedContextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
Thread.currentThread().setContextClassLoader(extensionClassLoader);
|
||||
internalStart();
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(savedContextClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
private void internalStart() {
|
||||
Iterator<LoggingCustomizer> loggingCustomizers =
|
||||
ServiceLoader.load(LoggingCustomizer.class).iterator();
|
||||
ServiceLoader.load(LoggingCustomizer.class, extensionClassLoader).iterator();
|
||||
LoggingCustomizer loggingCustomizer;
|
||||
if (loggingCustomizers.hasNext()) {
|
||||
loggingCustomizer = loggingCustomizers.next();
|
||||
|
@ -84,7 +75,7 @@ public class AgentStarterImpl implements AgentStarter {
|
|||
Throwable startupError = null;
|
||||
try {
|
||||
loggingCustomizer.init();
|
||||
AgentInstaller.installBytebuddyAgent(instrumentation);
|
||||
AgentInstaller.installBytebuddyAgent(instrumentation, extensionClassLoader);
|
||||
WeakConcurrentMapCleaner.start();
|
||||
} catch (Throwable t) {
|
||||
// this is logged below and not rethrown to avoid logging it twice
|
||||
|
|
|
@ -5,11 +5,9 @@
|
|||
|
||||
package io.opentelemetry.javaagent.tooling;
|
||||
|
||||
import io.opentelemetry.javaagent.bootstrap.AgentInitializer;
|
||||
import io.opentelemetry.javaagent.bootstrap.OpenTelemetrySdkAccess;
|
||||
import io.opentelemetry.sdk.OpenTelemetrySdk;
|
||||
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
||||
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder;
|
||||
import io.opentelemetry.sdk.common.CompletableResultCode;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
@ -21,17 +19,14 @@ public final class OpenTelemetryInstaller {
|
|||
*
|
||||
* @return the {@link AutoConfiguredOpenTelemetrySdk}
|
||||
*/
|
||||
public static AutoConfiguredOpenTelemetrySdk installOpenTelemetrySdk() {
|
||||
AutoConfiguredOpenTelemetrySdkBuilder builder =
|
||||
AutoConfiguredOpenTelemetrySdk.builder().setResultAsGlobal(true);
|
||||
public static AutoConfiguredOpenTelemetrySdk installOpenTelemetrySdk(
|
||||
ClassLoader extensionClassLoader) {
|
||||
|
||||
ClassLoader classLoader = AgentInitializer.getExtensionsClassLoader();
|
||||
if (classLoader != null) {
|
||||
// May be null in unit tests.
|
||||
builder.setServiceClassLoader(classLoader);
|
||||
}
|
||||
|
||||
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk = builder.build();
|
||||
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
|
||||
AutoConfiguredOpenTelemetrySdk.builder()
|
||||
.setResultAsGlobal(true)
|
||||
.setServiceClassLoader(extensionClassLoader)
|
||||
.build();
|
||||
OpenTelemetrySdk sdk = autoConfiguredSdk.getOpenTelemetrySdk();
|
||||
|
||||
OpenTelemetrySdkAccess.internalSetForceFlush(
|
||||
|
|
|
@ -30,9 +30,9 @@ public final class SafeServiceLoader {
|
|||
*/
|
||||
// Because we want to catch exception per iteration
|
||||
@SuppressWarnings("ForEachIterable")
|
||||
public static <T> List<T> load(Class<T> serviceClass) {
|
||||
public static <T> List<T> load(Class<T> serviceClass, ClassLoader classLoader) {
|
||||
List<T> result = new ArrayList<>();
|
||||
ServiceLoader<T> services = ServiceLoader.load(serviceClass);
|
||||
ServiceLoader<T> services = ServiceLoader.load(serviceClass, classLoader);
|
||||
for (Iterator<T> iterator = new SafeIterator<>(services.iterator()); iterator.hasNext(); ) {
|
||||
T service = iterator.next();
|
||||
if (service != null) {
|
||||
|
@ -43,11 +43,12 @@ public final class SafeServiceLoader {
|
|||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #load(Class)}, but also orders the returned implementations by comparing their
|
||||
* {@link Ordered#order()}.
|
||||
* Same as {@link #load(Class, ClassLoader)}, but also orders the returned implementations by
|
||||
* comparing their {@link Ordered#order()}.
|
||||
*/
|
||||
public static <T extends Ordered> List<T> loadOrdered(Class<T> serviceClass) {
|
||||
List<T> result = load(serviceClass);
|
||||
public static <T extends Ordered> List<T> loadOrdered(
|
||||
Class<T> serviceClass, ClassLoader classLoader) {
|
||||
List<T> result = load(serviceClass, classLoader);
|
||||
result.sort(Comparator.comparing(Ordered::order));
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.google.auto.service.AutoService;
|
|||
import io.opentelemetry.javaagent.bootstrap.InstrumentationHolder;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
||||
import io.opentelemetry.javaagent.tooling.AgentExtension;
|
||||
import io.opentelemetry.javaagent.tooling.Utils;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import java.util.logging.Logger;
|
||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||
|
@ -27,7 +28,8 @@ public class InstrumentationLoader implements AgentExtension {
|
|||
@Override
|
||||
public AgentBuilder extend(AgentBuilder agentBuilder, ConfigProperties config) {
|
||||
int numberOfLoadedModules = 0;
|
||||
for (InstrumentationModule instrumentationModule : loadOrdered(InstrumentationModule.class)) {
|
||||
for (InstrumentationModule instrumentationModule :
|
||||
loadOrdered(InstrumentationModule.class, Utils.getExtensionsClassLoader())) {
|
||||
if (logger.isLoggable(FINE)) {
|
||||
logger.log(
|
||||
FINE,
|
||||
|
|
|
@ -61,7 +61,7 @@ class HelperInjectionTest extends Specification {
|
|||
def "helpers injected on bootstrap classloader"() {
|
||||
setup:
|
||||
ByteBuddyAgent.install()
|
||||
AgentInstaller.installBytebuddyAgent(ByteBuddyAgent.getInstrumentation())
|
||||
AgentInstaller.installBytebuddyAgent(ByteBuddyAgent.getInstrumentation(), this.class.classLoader)
|
||||
String helperClassName = HelperInjectionTest.getPackage().getName() + '.HelperClass'
|
||||
HelperInjector injector = new HelperInjector("test", [helperClassName], [], this.class.classLoader, ByteBuddyAgent.getInstrumentation())
|
||||
URLClassLoader bootstrapChild = new URLClassLoader(new URL[0], (ClassLoader) null)
|
||||
|
|
|
@ -24,7 +24,7 @@ class OpenTelemetryInstallerTest extends Specification {
|
|||
|
||||
def "should initialize GlobalOpenTelemetry"() {
|
||||
when:
|
||||
def otelInstaller = OpenTelemetryInstaller.installOpenTelemetrySdk()
|
||||
def otelInstaller = OpenTelemetryInstaller.installOpenTelemetrySdk(OpenTelemetryInstaller.classLoader)
|
||||
|
||||
then:
|
||||
otelInstaller != null
|
||||
|
|
|
@ -46,7 +46,7 @@ class ConfigurationFileLoaderTest {
|
|||
|
||||
// when
|
||||
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
|
||||
OpenTelemetryInstaller.installOpenTelemetrySdk();
|
||||
OpenTelemetryInstaller.installOpenTelemetrySdk(this.getClass().getClassLoader());
|
||||
|
||||
// then
|
||||
assertThat(autoConfiguredSdk.getConfig().getString("custom.key")).isEqualTo("42");
|
||||
|
|
|
@ -32,7 +32,8 @@ public final class AgentTooling {
|
|||
|
||||
private static ClassLoader getBootstrapProxy() {
|
||||
Iterator<BootstrapProxyProvider> iterator =
|
||||
ServiceLoader.load(BootstrapProxyProvider.class).iterator();
|
||||
ServiceLoader.load(BootstrapProxyProvider.class, AgentTooling.class.getClassLoader())
|
||||
.iterator();
|
||||
if (iterator.hasNext()) {
|
||||
BootstrapProxyProvider bootstrapProxyProvider = iterator.next();
|
||||
return bootstrapProxyProvider.getBootstrapProxy();
|
||||
|
|
|
@ -33,7 +33,7 @@ public class ClassLoaderMatcher {
|
|||
public static Map<String, List<Mismatch>> matchesAll(
|
||||
ClassLoader classLoader, boolean injectHelpers, Set<String> excludedInstrumentationNames) {
|
||||
Map<String, List<Mismatch>> result = new HashMap<>();
|
||||
ServiceLoader.load(InstrumentationModule.class)
|
||||
ServiceLoader.load(InstrumentationModule.class, ClassLoaderMatcher.class.getClassLoader())
|
||||
.forEach(
|
||||
module -> {
|
||||
if (module.instrumentationNames().stream()
|
||||
|
|
|
@ -26,7 +26,7 @@ public final class ReferencesPrinter {
|
|||
*/
|
||||
public static void printMuzzleReferences() {
|
||||
for (InstrumentationModule instrumentationModule :
|
||||
ServiceLoader.load(InstrumentationModule.class)) {
|
||||
ServiceLoader.load(InstrumentationModule.class, ReferencesPrinter.class.getClassLoader())) {
|
||||
try {
|
||||
System.out.println(instrumentationModule.getClass().getName());
|
||||
for (ClassRef ref :
|
||||
|
|
|
@ -10,6 +10,7 @@ import static java.util.logging.Level.SEVERE;
|
|||
import io.opentelemetry.javaagent.extension.ignore.IgnoredTypesConfigurer;
|
||||
import io.opentelemetry.javaagent.tooling.EmptyConfigProperties;
|
||||
import io.opentelemetry.javaagent.tooling.SafeServiceLoader;
|
||||
import io.opentelemetry.javaagent.tooling.Utils;
|
||||
import io.opentelemetry.javaagent.tooling.ignore.AdditionalLibraryIgnoredTypesConfigurer;
|
||||
import io.opentelemetry.javaagent.tooling.ignore.GlobalIgnoredTypesConfigurer;
|
||||
import io.opentelemetry.javaagent.tooling.ignore.IgnoreAllow;
|
||||
|
@ -51,7 +52,8 @@ public class TestAgentListener implements AgentBuilder.Listener {
|
|||
private static Trie<IgnoreAllow> buildOtherConfiguredIgnores() {
|
||||
IgnoredTypesBuilderImpl builder = new IgnoredTypesBuilderImpl();
|
||||
for (IgnoredTypesConfigurer configurer :
|
||||
SafeServiceLoader.loadOrdered(IgnoredTypesConfigurer.class)) {
|
||||
SafeServiceLoader.loadOrdered(
|
||||
IgnoredTypesConfigurer.class, Utils.getExtensionsClassLoader())) {
|
||||
// skip built-in agent ignores
|
||||
if (configurer instanceof AdditionalLibraryIgnoredTypesConfigurer
|
||||
|| configurer instanceof GlobalIgnoredTypesConfigurer) {
|
||||
|
|
Loading…
Reference in New Issue