feat(engine-java): install path for AOT compiled-module classes (step 1 - the engine seam)#6400
Open
delchev wants to merge 2 commits into
Open
feat(engine-java): install path for AOT compiled-module classes (step 1 - the engine seam)#6400delchev wants to merge 2 commits into
delchev wants to merge 2 commits into
Conversation
…ild() Behavior-preserving split so the generation-install path (diff vs current -> notify consumers unload/load -> swap client loader -> rebuild bean container -> record) is source-agnostic: it takes a pre-built FQN->LoadedClass map + the loader. rebuild() still owns compile + effective-bytecode + class-file write + JavaCompiledEvent and calls applyGeneration() for the install. Foundation for AOT-packaged `compiled` modules, where a second producer discovers already-compiled classes on the classpath and drives the identical install path (no runtime javac). No functional change; 66 engine-java tests green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… compiled-module classes Second producer for the install path (AOT packaging): compiled-module classes already loaded by the application classloader are recorded as the `compiledGeneration` and surfaced to the same JavaClassConsumers via applyGeneration - NO runtime javac. The installed generation is now the union of the registry-compiled (rebuild) and classpath-compiled sub-generations, so a registry rebuild does not unload compiled modules and vice-versa. FQN clash between the two logs a warning (a mis-assembled image; the "exactly one provider" assembly check catches it earlier). Unit test: installCompiledModules registers a compiled class through the consumer path, and it survives a registry rebuild that drops all authored sources (not reported in unloadedFqns). engine- java 67/67 green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Step 1 of AOT (ahead-of-time) module packaging: teach
engine-javato register a module'salready-compiled classes (shipped on the application classpath) through the same consumer /
bean-container path it uses for runtime-compiled registry sources - without invoking
javac.This PR lands only the engine seam + unit tests; it does not yet wire a discovery producer or
change packaging (see Follow-ups). It's intentionally small so the core-loading change can be
reviewed on its own.
Changes
JavaLoader.applyGeneration(nextGeneration, loader)- extracted (behavior-preserving) fromrebuild(). It is the source-agnostic install: diff vs the current generation → notify everyJavaClassConsumer(unload → load) → swap the clientClassLoader→ rebuild the client beancontainer → record.
rebuild()still owns compile + effective-bytecode +.classwrite +JavaCompiledEvent, and calls it.JavaLoader.installCompiledModules(List<LoadedClass>)- a second producer: compiled-moduleclasses (already loaded by the application classloader) are recorded as the
compiledGenerationand installed via
applyGeneration. The installed generation is now the union of theregistry-compiled and classpath-compiled sub-generations, so a registry rebuild never unloads a
compiled module and vice-versa. An FQN clash between the two logs a warning (a mis-assembled
image).
Every
JavaClassConsumer(ControllerClassConsumer, listeners, websockets, handlers, scheduled,EntityClassConsumer) and theComponentContainerare unchanged - they already react to aloaded
Class, agnostic of how it was produced.Why
Deployed apps today compile client
.javafrom the registry at start (JavaSourceCompiler), whichis slow, all-or-nothing (one bad unit unregisters everything), and not immutable (no artifact
coordinate to scan for CVEs). The target is: ship modules as precompiled, versioned, signed jars on
the classpath and only run synchronizers on start. This PR is the minimal engine change that lets a
compiled module's controllers/DAOs/delegates register from the classpath.
Verification
engine-java67/67 green, incl. a newJavaLoaderTestcase:installCompiledModulesregisters acompiled class through the consumer path, and it survives a registry rebuild that drops all authored
sources (absent from
unloadedFqns).Follow-ups (separate PRs)
META-INF/dirigible/<project>/compiled-module markers (surfaced tothe registry by the existing
ClasspathExpander),Class.forNamethe listed FQNs on the appclassloader, call
installCompiledModulesat startup.compiled-mode gate inJavaSynchronizer- skip.javafor compiled modules (no runtimejavac).META-INF/dirigible/<project>content, no.java) + POM with cross-model deps.javacnever invoked.🤖 Generated with Claude Code