Fix class loading instrumentation
This commit is contained in:
parent
55276148b9
commit
0984ac2a61
|
@ -71,32 +71,39 @@ public final class ClassloadingInstrumentation extends Instrumenter.Default {
|
||||||
|
|
||||||
public static class LoadClassAdvice {
|
public static class LoadClassAdvice {
|
||||||
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
|
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
|
||||||
public static Class<?> onEnter(
|
public static Class<?> onEnter(@Advice.Argument(0) final String name) {
|
||||||
@Advice.Argument(0) final String name, @Advice.Local("_callDepth") int callDepth) {
|
// need to use call depth here to prevent re-entry from call to Class.forName() below
|
||||||
callDepth = CallDepthThreadLocalMap.incrementCallDepth(ClassLoader.class);
|
// because on some JVMs (e.g. IBM's, though IBM bootstrap loader is explicitly excluded above)
|
||||||
|
// Class.forName() ends up calling loadClass() on the bootstrap loader which would then come
|
||||||
|
// back to this instrumentation over and over, causing a StackOverflowError
|
||||||
|
final int callDepth = CallDepthThreadLocalMap.incrementCallDepth(ClassLoader.class);
|
||||||
if (callDepth > 0) {
|
if (callDepth > 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
for (final String prefix : Constants.BOOTSTRAP_PACKAGE_PREFIXES) {
|
try {
|
||||||
if (name.startsWith(prefix)) {
|
for (final String prefix : Constants.BOOTSTRAP_PACKAGE_PREFIXES) {
|
||||||
try {
|
if (name.startsWith(prefix)) {
|
||||||
return Class.forName(name, false, null);
|
try {
|
||||||
} catch (final ClassNotFoundException e) {
|
return Class.forName(name, false, null);
|
||||||
|
} catch (final ClassNotFoundException e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
// need to reset it right away, not waiting until onExit()
|
||||||
|
// otherwise it will prevent this instrumentation from being applied when loadClass()
|
||||||
|
// ends up calling a ClassFileTransformer which ends up calling loadClass() further down the
|
||||||
|
// stack on one of our bootstrap packages (since the call depth check would then suppress
|
||||||
|
// the nested loadClass instrumentation)
|
||||||
|
CallDepthThreadLocalMap.reset(ClassLoader.class);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class)
|
@Advice.OnMethodExit(onThrowable = Throwable.class)
|
||||||
public static void onExit(
|
public static void onExit(
|
||||||
@Advice.Local("_callDepth") final int callDepth,
|
|
||||||
@Advice.Return(readOnly = false) Class<?> result,
|
@Advice.Return(readOnly = false) Class<?> result,
|
||||||
@Advice.Enter final Class<?> resultFromBootstrapLoader) {
|
@Advice.Enter final Class<?> resultFromBootstrapLoader) {
|
||||||
if (callDepth > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CallDepthThreadLocalMap.reset(ClassLoader.class);
|
|
||||||
if (resultFromBootstrapLoader != null) {
|
if (resultFromBootstrapLoader != null) {
|
||||||
result = resultFromBootstrapLoader;
|
result = resultFromBootstrapLoader;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue