Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove scanning and loading of all classes at beginning of image build #2599

Open
christianwimmer opened this issue Jun 22, 2020 · 4 comments

Comments

@christianwimmer
Copy link
Member

christianwimmer commented Jun 22, 2020

TL;DR

The image generator should not scan the complete class path and load all classes on the class path. This slows down image builds.

Details

The first step of building a native image is a complete class path scan: all classes of the provided application class path are loaded in the hosting Java HotSpot VM. This was an early design decision in Native Image that allows the image builder to

  • query all subtypes of a provided type (including all implementations of an interface), and
  • query all classes / methods / fields that have a certain annotation.

But the approach is problematic for several reasons:

  • Loading all classes is time consuming. For larger applications and benchmarks, 30 seconds are not uncommon.
  • If no class path is provided explicitly, the current working directory is the class path. If the current working directory is the user's home directory (or even the file system root as it is common in Docker), large parts of the file system are scanned and it appears as if the native image tool is hanging.
  • Class loading can already throw errors when the class path is incomplete or classes do not verify. Such classes are silently ignored during classpath scanning, which can lead to surprisingly missing classes in the queries.
  • The JDK itself is not scanned. Additional class loader used by the application are not scanned. So the list of subtypes and annotated elements is never a complete and reliable "closed world view".

Access to the list of all classes and annotated elements is not possible via the supported API in org.graalvm.nativeimage. However, we are aware that several frameworks that support Native Image access the information by reaching into implementation-specific data structures. These frameworks need to adapt before the code can be removed from native image.

Alternatives:

  • Instead of scanning all elements, scan only the elements reachable already by the static analysis. The static analysis has a convenient API to register hooks and listeners.
  • Move the scanning code into the application and framework, using a library of your choice or implement the scanning yourself. For this, we need to provide the class path of the application via the native image API (see Provide access to the application class path of the image that is currently built #2600)

Internally, several parts of native image currently rely on the class path information. This list is not exhaustive, but only a starting point of things that need to change:

  • The low-level C interface provided in org.graalvm.nativeimage.c uses annotations. Annotated elements are processed before the static analysis to query values from the imported C libraries. Alternatives: Do these queries as a separate step before image building (which also simplifies cross compilation).
  • Find all entry points from C code (annotated with @CEntryPoint)
  • Find all @TargetClass annotated classes that have substitutions. Alternative: use service loader to find substitution classes.
  • Find subclasses when registering classes for initialization at build time / run time in ConfigurableClassInitialization
  • Support code for JavaFX and Scala that ships as part of Native Image
  • Registration of graph build plugins for node intrinsics
@adinn
Copy link
Collaborator

adinn commented Jun 23, 2020

Hi Chistian,

This sounds like an 'interesting' change -- but also one well worth investigating :-).

I think the idea of providing hooks for consumers of native image to direct the class graph search sounds very promising. Red Hat are keen to help with implementing changes along these lines.

@vjovanov vjovanov modified the milestones: 20.3, 21.1 Jun 23, 2020
@kirillp
Copy link

kirillp commented Nov 24, 2020

what about this @TargetClass and @Substitute?

Without scanning GraalVM can never see this classes.

@TargetClass(value = Png.class)
public final class PngReplacement {
  @Substitute long encodeRGBA(...); 
}

@christianwimmer
Copy link
Member Author

what about this @TargetClass and @substitute?

The easiest way to handle these things will be annotation processing when the source code is compiled, i.e., let javac already collect the list of annotated classes.

@gilles-duboscq
Copy link
Member

gilles-duboscq commented Jun 15, 2021

This is still on the 21.1 milestone, which milestone should it be moved to?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: In Progress
Native Image
  
To do
Development

No branches or pull requests

6 participants