diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/InstrumentationModuleClassLoader.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/InstrumentationModuleClassLoader.java index fada8911eb71..4412e63b8b9a 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/InstrumentationModuleClassLoader.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/InstrumentationModuleClassLoader.java @@ -109,10 +109,15 @@ public MethodHandles.Lookup getLookup() { if (cachedLookup == null) { // Load the injected copy of LookupExposer and invoke it try { + MethodType getLookupType = MethodType.methodType(MethodHandles.Lookup.class); // we don't mind the race condition causing the initialization to run multiple times here Class lookupExposer = loadClass(LookupExposer.class.getName()); - cachedLookup = (MethodHandles.Lookup) lookupExposer.getMethod("getLookup").invoke(null); - } catch (Exception e) { + // Note: we must use MethodHandles instead of reflection here to avoid a recursion + // for our internal ReflectionInstrumentationModule which instruments reflection methods + cachedLookup = (MethodHandles.Lookup) MethodHandles.publicLookup() + .findStatic(lookupExposer, "getLookup", getLookupType) + .invoke(); + } catch (Throwable e) { throw new IllegalStateException(e); } }