Description
In order to compile to native images and to provide a reasonable footprint, we are currently forced to initialize classes containing ClassUtils#isPresent
checks at build time. A meaningful concrete example of that requirement is provided by Spring MVC support that does not compile unless a few classes are initialized at build time, see 2b76a12.
The drawback is that this build time init of WebMvcConfigurationSupport
and RestTemplate
forces to initialize transitively all classes used in static fields/blocks at build time as well : ClassUtils
, SpringProperties
, ConcurrentReferenceHashMap
. Worse : for other classes with similar pattern, if they contain a static loggers, this will force to initialize Logback at build time which is a dead end in term of compatibility as shown multiple times in Spring Native.
We are working on a middle-long term solution with GraalVM to replace build time init by another mechanism, less viral, with less compatibility issues. But for time being, we need to find a solution to this issue.
A pragmatic solution would be isolate classpath checks in a per module (spring-core
, spring-web
) class that would be itself init at build time but with no other purpose, removing the risk of viral expension of the classes init at build time. If we take the WebMvcConfigurationSupport
use case, we would have something like:
public abstract class ClasspathUtils {
private static final boolean romePresent;
private static final boolean jaxb2Present;
private static final boolean jackson2Present;
static {
// ...
}
public static boolean isRomePresent() { ... }
public static boolean isJaxb2Present() { ... }
public static boolean isJackson2Present() { ... }
// ...
}
Bonus point, I think I like the fact that we provide reusable methods for classpath checks without arbitrary String
parameter.
Implementation would potentially even not use ClassUtils
to limit the classes init at build time (not sure what is would use instead, to be discussed, not a blocking point).