Open bilak opened 3 years ago
Fix on JMockit's side? Probably not, if it would require me digging into a lot of unknown code... If a reproduceable, self-contained, test case can be shown here, I can take a look.
Hi I spend wholed day with debuging and trying to resolve it and now I know where is the issue. But I do not know how to fix it in general. The problem happens when this is called in Startup.getClassIfLoaded
:
@SuppressWarnings("ConstantConditions") Class<?>[] loadedClasses = instrumentation.getAllLoadedClasses();
I do not know why. I suspect classloaders. Here is the new code in Tomcat which is problematic:
factory = AccessController.doPrivileged(
(PrivilegedExceptionAction<AuthConfigFactory>) () -> {
// Load this class with the same class loader as used for
// this class. Note that the Thread context class loader
// should not be used since that would trigger a memory leak
// in container environments.
if (className.equals("org.apache.catalina.authenticator.jaspic.AuthConfigFactoryImpl")) {
return new org.apache.catalina.authenticator.jaspic.AuthConfigFactoryImpl();
} else {
Class<?> clazz = Class.forName(className);
return (AuthConfigFactory) clazz.getConstructor().newInstance();
}
});
and old one which works:
factory = AccessController.doPrivileged(
new PrivilegedExceptionAction<AuthConfigFactory>() {
@Override
public AuthConfigFactory run() throws ReflectiveOperationException,
IllegalArgumentException, SecurityException {
// Load this class with the same class loader as used for
// this class. Note that the Thread context class loader
// should not be used since that would trigger a memory leak
// in container environments.
if (className.equals("org.apache.catalina.authenticator.jaspic.AuthConfigFactoryImpl")) {
return new org.apache.catalina.authenticator.jaspic.AuthConfigFactoryImpl();
} else {
Class<?> clazz = Class.forName(className);
return (AuthConfigFactory) clazz.getConstructor().newInstance();
}
}
});
So there is only replacement of the annonynmous class with the lambda expression.
I found two workarounds:
CapturedType.isNotToBeCaptured
and add there another non eligible class org.apache.catalina.authenticator.jaspic.AuthConfigFactoryImpl
. Maybe there could be some configuration file for it where users can define there non eligable classes.The second workaround is pretty stupid. Just add a field of type AuthConfigFactoryImpl
into a test with @Capturing
.
AuthConfigFactoryImpl hack;
@Capturing
private TestService testService;
From my point of view the issue is in JDK and java.lang.instrument.Instrumentation.getAllLoadedClasses()
And here is exactly the same issue with ASM: https://stackoverflow.com/questions/47169763/asm-5-2-java-lang-linkage-error-when-instrumenting-apachhttpclient
We are using
@Capturing
on field for long time. It was working correctly until recent changes in tomcat. Here is a bug that I've reported and here is the application on which it can be tested.Do you think this can be fixed on jmockit site?