-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
Description
The GraalVM native-image
tool can take an option --allow-incomplete-classpath
which changes how it deals with unresolved symbols found during reachability analisys.
Normally, when running an application on a regular JVM, code can refer to optional dependencies and the application can still boot; if the code is triggered at runtime and refers to a class which can't be loaded, a CNFE is thrown - but in native-image, when this flag is not set, resolution is validated at build time.
In the past we did like the native-image approach, for several reasons:
- it helps validate the closed world application is fully valid and defined
- setting
--allow-incomplete-classpath
was having some additional odd side-effects, such as making reachability reports more confusing (this was most likely a bug).
In hotspot it wouldn't have been reasonable to have a similar validation, as it needs to support non-closed-world use cases. Essentially I (personally) considered it a "nice feature" of native-image, however it comes with problems: some libraries actually do rely on optional dependencies and don't use a clean decoupling mechanism like ServiceLoader
. I have been hoping that the native-image approach would encourage library maintainers to use the ServiceLoader
mechanism, but it's been some years and we still have problems with at least two notable dependencies:
- the Oracle JDBC driver
- the MSSQL JDBC driver
Both of these libraries have several optional dependencies; in the case of the MSSQL driver we patch this with subsitutions but this causes problems for people who actually want to use the optional capabilities. In the case of the Oracle driver we can't do much as it's closed source - currently the use of this driver triggers the use of --allow-incomplete-classpath
but this has global impact, so it raises quality concerns as this mode is less so tested in combination with other extensions.
I've discussed this pending problem with @christianwimmer @jerboaa @maxandersen today and we came to the conclusion that perhaps native-image should default to the same semantics as hotspot: to have the --allow-incomplete-classpath
set by default. The "odd side effects" that we had observed in early days are very likely no longer applicable, as it's been years since that time.
The proposal here is to set this flag by default in Quarkus, to verify that it doesn't break any other extension and has no other surprises; based on our feedback, native-image might also flip its default.
This would resolve the immediate issues with those JDBC drivers: we wouldn't need substitutions in MSSQL, the Oracle driver wouldn't be setting an untested global flag, and possibly other libraries would benefit as well as it brings us semantics closer to hotspot.
We would still be able to revert the behaviour, which has been useful to verify consistency at build time.
Implementation ideas
- Set
--allow-incomplete-classpath
by default in when Quarkus runs a native compilation - Test it all, provide feedback to the GraalVM team
- Document suggestions about how to potentially revert the behaviour (might not be trivial as we'd need to remove a flag we set)