feat(engine-java): classpath loading of AOT compiled modules (no runtime javac)#6400
Merged
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>
…AOT compiled modules The producer that drives installCompiledModules: on ApplicationReadyEvent it scans the classpath for META-INF/dirigible/<project>/.compiled markers (a UTF-8 list of the module's top-level class binary names, # comments allowed), derives the project from the path, Class.forName's each through the application classloader, and installs them - no runtime javac. Reads markers straight from the classpath, so it does not depend on the ClasspathExpander laying the registry payload first; a later registry rebuild unions the compiled classes back in. Unit test + fixture (AotFixtureClass + a test .compiled marker): discover() finds the marker, derives project "aot-test-mod", and loads the listed class via the app classloader. engine-java 68/68 green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… (no javac) Integration test closing the loop for AOT classpath loading: a @controller shipped by a compiled module - installed via JavaLoader.installCompiledModules rather than compiled from registry source - is instantiated by the ComponentContainer, registered by the standard ControllerClassConsumer, and its GET route resolves through ControllerRouter. Proves the outermost engine-reachable layer (served route) without any runtime javac. engine-java 69/69 green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
| } | ||
|
|
||
| @Override | ||
| public void publishEvent(Object event) { |
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
Engine-side support for AOT (ahead-of-time) module packaging: register a module's
already-compiled classes (shipped on the application classpath) through the same consumer /
bean-container path used for runtime-compiled registry sources - without invoking
javac.Changes
JavaLoader.applyGeneration(nextGeneration, loader)- extracted (behavior-preserving) fromrebuild(): the source-agnostic install (diff → notifyJavaClassConsumers unload/load → swapclient
ClassLoader→ rebuild client bean container → record).JavaLoader.installCompiledModules(List<LoadedClass>)- second producer. Compiled-moduleclasses become the
compiledGeneration; the installed generation is the union ofregistry-compiled + classpath-compiled sub-generations, so neither producer unloads the other.
CompiledModuleClassProvider- onApplicationReadyEvent, scans the classpath forMETA-INF/dirigible/<project>/.compiledmarkers (a UTF-8 list of the module's top-level classbinary names),
Class.forNames each via the application classloader, and installs them. Readsmarkers straight from the classpath, independent of the
ClasspathExpander.Every
JavaClassConsumer(ControllerRouter, listeners, websockets, handlers, scheduled,EntityClassConsumer) and theComponentContainerare unchanged - they already react to aloaded
Class, agnostic of how it was produced.No
JavaSynchronizergate needed (by design)A compiled module ships only
.class(classpath) +META-INF/dirigible/<project>content(models/UI/data) - no
.javain its registry payload.JavaSynchronizerfinds nothing tocompile for it (absence of
.javais the gate), and theJavaLoaderunion makes the two producerscoexist.
Verification -
engine-java69/69JavaLoaderTest:installCompiledModulesregisters a compiled class through the consumer path andit survives a registry rebuild that drops all authored sources.
CompiledModuleClassProviderTest: a.compiledmarker on the classpath is discovered, the projectderived from the path, and the listed class loaded via the app classloader.
CompiledModuleControllerRegistrationTest(end-to-end): a@Controllershipped by a compiledmodule is instantiated by the
ComponentContainer, registered by the standardControllerClassConsumer, and its GET route resolves throughControllerRouter- proving theoutermost engine-reachable layer (a served route) with no runtime
javac.Follow-ups (separate)
META-INF/dirigible/<project>content + the emitted
.compiledmarker (no.java) + POM with cross-model deps; image assemblyfrom pinned versions.
BOOT-INF/lib→ HTTP 200) - largelyredundant now that route resolution is proven at the component level above.
🤖 Generated with Claude Code