Class RuntimeClassExtractor

java.lang.Object
org.ek9lang.core.RuntimeClassExtractor

public final class RuntimeClassExtractor extends Object
Extracts EK9 runtime classes (org.ek9.lang and ek9 packages) from the running JVM and packages them into a versioned JAR file with SHA-256 checksum.

This enables per-project runtime caching, keyed on the compiler version AND a content hash of the runtime classes (RuntimeContentHash): - First build: Extract EK9 runtime + dependency classes from compiler JVM → create JAR + checksum - Subsequent builds: Reuse cached JAR if checksum valid - A different compiler (another version, or a development build that kept its version but changed its runtime) gets its own JAR, and the superseded entries are removed - the cache holds one.

The version alone was the key until 2026-10-05 (Steve decision E): a development build with an unchanged version then packaged the STALE cached runtime into every program jar, which surfaced as NoClassDefFoundError: org/ek9/lang/UncaughtFailure until .ek9/ was deleted.

Extracts all EK9 runtime classes plus third-party dependencies (Jackson, SLF4J) including inner and anonymous classes required for runtime functionality. Uses direct JAR scanning with standard Java APIs (JarFile, ClassLoader).

  • Field Details

    • RUNTIME_AND_DEPENDENCY_PACKAGES

      static final List<String> RUNTIME_AND_DEPENDENCY_PACKAGES
      RUNTIME_PACKAGES then DEPENDENCY_PACKAGES: everything the runtime jar takes.
    • NOTICES_RESOURCE

      static final String NOTICES_RESOURCE
      THE notices of the third-party code in every compiled program (the DEPENDENCY_PACKAGES), written into the runtime jar - and so into each program jar - at NOTICES_ENTRY. Their licences (Apache-2.0, MIT) ask that the notice travel with every copy, and whoever ships an EK9 program ships these libraries. A dependency package added above needs its entry there (RuntimeClassExtractorTest checks), and in THIRD_PARTY_NOTICES.md. It also carries libinjection's BSD-3-Clause notice: the runtime's SQL injection detection (SqlTokenizer, SqlInjectionFingerprints) is derived from it, so it travels with every program though it is no package here.
      See Also:
    • NOTICES_ENTRY

      public static final String NOTICES_ENTRY
      Where the notices go in the runtime jar, and so in every program jar.
      See Also:
    • RUNTIME_LICENCE_RESOURCE

      static final String RUNTIME_LICENCE_RESOURCE
      The runtime's own licence, the Apache License 2.0 (licence decision D-L1, docs/legal), and its NOTICE: Apache-2.0 s.4 asks that both travel with every copy of the runtime, and every program jar is one. THE texts are ek9-lang/LICENSE and ek9-lang/NOTICE, packaged into the runtime module at these resource paths.
      See Also:
    • RUNTIME_NOTICE_RESOURCE

      static final String RUNTIME_NOTICE_RESOURCE
      The runtime's NOTICE, as packaged into the runtime module.
      See Also:
    • RUNTIME_LICENCE_ENTRY

      public static final String RUNTIME_LICENCE_ENTRY
      Where the runtime's licence goes in the runtime jar, and so in every program jar.
      See Also:
    • RUNTIME_NOTICE_ENTRY

      public static final String RUNTIME_NOTICE_ENTRY
      Where the runtime's NOTICE goes in the runtime jar, and so in every program jar.
      See Also:
  • Constructor Details

    • RuntimeClassExtractor

      public RuntimeClassExtractor()
  • Method Details

    • extractRuntimeJar

      public Optional<File> extractRuntimeJar(FileHandling fileHandling, String projectDir, String version)
      Extract EK9 runtime classes into a JAR file keyed on the version and RuntimeContentHash. Creates JAR at: <projectDir>/.ek9/runtime/ek9-runtime-<version>-<contentHash>.jar Also creates corresponding .sha256 checksum file, and removes every superseded cache entry.
      Parameters:
      fileHandling - FileHandling instance for JAR creation and checksums
      projectDir - Project directory (source file directory)
      version - Compiler version (e.g., "0.0.1-0")
      Returns:
      Optional containing the runtime JAR file if successful
    • extractRuntimeJar

      Optional<File> extractRuntimeJar(FileHandling fileHandling, String projectDir, String version, String contentHash)
      As extractRuntimeJar(FileHandling, String, String) but with the content hash given, so a test can stand in for a changed runtime.