You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Runtime Java compilation — Provides an API for compiling Java source code at runtime, supporting both in-memory and file-based output
Pluggable compiler backends — Supports the JDK system compiler (javac via ToolProvider) and Eclipse Compiler for Java (ECJ) as interchangeable strategies
OSGi integration — Full support for OSGi environments with bundle-aware classloading, dynamic compiler service registration via Declarative Services, and Karaf deployment
Flexible classloading — Composite classloaders, custom classloader wrapping, and compiled-bytecode classloaders enable loading compiled classes in complex classloader hierarchies
ServiceLoader discovery — Compiler factories are discovered automatically via java.util.ServiceLoader in standard Java, or via OSGi DS @Reference in OSGi containers
Code Instructions
First think through the problem, read the codebase for relevant files.
Before you make any major changes, check in with me and I will verify the plan.
Please every step of the way just give me a high level explanation of what changes you made.
Make every task and code change you do as simple as possible. We want to avoid making any massive or complex changes. Every change should impact as little code as possible. Everything is about simplicity.
Maintain a documentation file that describes how the architecture of the app works inside and out.
Never speculate about code you have not opened. If the user references a specific file, you MUST read the file before answering. Make sure to investigate and read relevant files BEFORE answering questions about the codebase. Never make any claims about code before investigating unless you are certain of the correct answer - give grounded and hallucination-free answers.
For implementation use TDD (Test-Driven Development): write or update tests first to define the expected behaviour, verify they fail, then write the minimal implementation to make them pass.
Use DRY (Don't Repeat Yourself): extract reusable logic into separate classes, utilities, or components. If the same pattern appears in multiple places, refactor it into a shared helper.
Core API with CompilerContext (builder), CompilerFactory (strategy interface), CompilerUtil (static compilation entry point), file managers, classloaders, and file objects
Compiler Implementations
Module
Type
Purpose
java-embedded-compiler-jdt/
OSGi Bundle
JdtCompilerFactory — wraps ToolProvider.getSystemJavaCompiler(). Requires a JDK (not JRE). Registered as OSGi component with compileType=system.
java-embedded-compiler-ecj/
OSGi Bundle
EclipseCompilerFactory — wraps the Eclipse ECJ compiler with a custom EclipseCompilerWrapper that handles two-pass compilation (module-info first, then sources). Registered as compileType=eclipse. Passes -warn:none by default.
Runtime & Integration
Module
Type
Purpose
java-embedded-compiler-osgi/
OSGi Bundle
CompilerService interface and CompilerServiceImpl DS component. Dynamically discovers CompilerFactory services, ranks them by SERVICE_RANKING, and selects the appropriate compiler based on CompilerContext.preferEclipseCompiler.
java-embedded-compiler-itest/
Test
Karaf 4.4.7 + Pax Exam 4.13.5 integration tests. Tests all compilation modes: file-to-directory, file-to-memory, string-to-memory, compile-as-class, and error handling — for both JDT and ECJ compilers.
java-embedded-compiler-reports/
Reports
JaCoCo aggregate coverage report across all modules.
Technology Stack
Core Technologies
Java 11 — source and target compatibility
Google Guava 30.0-jre — LoadingCache for in-memory file manager caching, ImmutableList, Preconditions
OSGi Core 6.0 — BundleContext, BundleWiring, BundleListener for bundle-aware compilation
OSGi Declarative Services 1.3 — @Component, @Reference annotations for service registration
Pax Exam 4.13.5 — OSGi container testing with Apache Karaf
JaCoCo 0.8.12 — Code coverage
SonarQube — Code quality analysis
Logback 1.5.12 — Test logging
Build Commands
The project includes a Maven wrapper. Always use ./mvnw (or mvnw.cmd on Windows).
# Full build
./mvnw clean install
# Tests only
./mvnw clean test# Skip tests
./mvnw clean install -DskipTests
# Build parent POM only (no sub-modules)
./mvnw clean install -DskipModules=true
# Run a specific test
./mvnw test -Dtest=CompilerUtilITest -f java-embedded-compiler-itest/pom.xml
# Deploy to Judong Nexus
./mvnw clean deploy -Prelease-judong
Maven Profiles
Profile
Purpose
modules
Active by default. Includes all sub-modules. Disable with -DskipModules=true.
sign-artifacts
GPG-sign artifacts for Maven Central publication.
release-dummy
Deploy to local /tmp/ directory for testing the release process.
release-judong
Deploy to the Judong Nexus snapshot repository.
release-central
Deploy to Maven Central via Sonatype OSSRH with auto-release.
generate-github-asciidoc-diagrams
Render PlantUML diagrams from AsciiDoc sources.
update-source-code-license
Update Apache 2.0 license headers across all source files.
Every commit must reference a JIRA ticket in the format JNG-xxx
CI/CD: GitHub Actions on judong runner with JDK 21. Builds deploy to Judong Nexus; release branches also deploy to Maven Central.
Important Notes
Two compiler modes exist — JDT (system javac) requires a full JDK to be present at runtime; ECJ works with just a JRE since it bundles its own compiler
In-memory is the default — When no outputDirectory is set on CompilerContext, compilation happens entirely in memory using InMemoryJavaFileManager with Guava caching
OSGi service ranking — CompilerServiceImpl selects the highest-ranked CompilerFactory unless preferEclipseCompiler is set, in which case it filters for the Eclipse implementation
Java 1.8 compilation target in CompilerUtil — The actual compilation target inside CompilerUtil is hardcoded to Java 1.8 (-source 1.8 -target 1.8), regardless of the JDK version used to run the build
ECJ two-pass compilation — EclipseCompilerWrapper performs a two-pass compilation: module-info files first, then remaining sources
Test resources — Integration test source files are in java-embedded-compiler-itest/src/test/resources/compile1/ (valid) and compile2/ (intentionally invalid for error testing)
All modules are OSGi bundles — Every module is packaged as an OSGi bundle via Felix maven-bundle-plugin, exporting hu.blackbelt.java.embedded.compiler.*
Class name typo — EclipeCompilerFactory (missing 's' in Eclipse) is the actual class name in the ECJ module; do not "fix" this without a coordinated rename
Related Documentation
README.md — Project overview with architecture diagrams
CONTRIBUTING.md — Development setup and submission guidelines