From 21e40437ebb87ca25e1861cb118c25ee9d10d20e Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Fri, 21 Nov 2025 20:22:28 +0000 Subject: [PATCH 01/13] Update decision log and project requirements documentation for Java Runtime Compiler --- src/main/docs/decision-log.adoc | 110 +++++++++++++++++- .../{adoc => docs}/project-requirements.adoc | 18 ++- 2 files changed, 122 insertions(+), 6 deletions(-) rename src/main/{adoc => docs}/project-requirements.adoc (74%) diff --git a/src/main/docs/decision-log.adoc b/src/main/docs/decision-log.adoc index d9c432c..8787d11 100644 --- a/src/main/docs/decision-log.adoc +++ b/src/main/docs/decision-log.adoc @@ -1,3 +1,24 @@ += Java Runtime Compiler Decision Log +Chronicle Software +:toc: +:sectnums: +:lang: en-GB +:source-highlighter: rouge + +This log records architectural and process choices for the Java Runtime Compiler. +Each entry uses the Nine-Box tag set and links back to `project-requirements.adoc` where possible. + +== Decision Index + +* RC-FN-001 Allow hyphenated descriptor class names +* RC-TEST-002 Align coverage gate with achieved baseline +* RC-FN-002 Cached compiler API and custom class loaders +* RC-NF-P-006 Performance and metaspace budget for cached compilation +* RC-RISK-026 Debug artefact directory safety + +== Decisions + +[[RC-FN-001]] === [RC-FN-001] Allow hyphenated descriptor class names * Date: 2025-10-28 @@ -34,4 +55,91 @@ ** Documentation for requirement JRC-TEST-014 is updated to the same value. * Notes/Links: ** Thresholds maintained in `pom.xml`. -** Updated requirement: `src/main/docs/project-requirements.adoc`. +** Updated requirement: `src/main/adoc/project-requirements.adoc` (JRC-TEST-014). + +[[RC-FN-002]] +=== [RC-FN-002] Cached compiler API and custom class loaders + +Date :: 2025-11-14 +Context :: +* Callers need a simple way to compile Java source from a string and obtain a `Class` at runtime. +* The project requirements JRC-FN-001 to JRC-FN-004 call for a singleton cached compiler and support for custom `ClassLoader` instances. +* Creating a new compiler for every call would waste CPU time and increase memory pressure. +Decision :: +* Use `CompilerUtils.CACHED_COMPILER` as the default entry point for simple compile and load operations. +* Expose `CachedCompiler` as a reusable component that caches compiled classes per class loader and supports optional debug directories for `.java` and `.class` files. +Alternatives :: +* Always construct a new `CachedCompiler` instance for each compilation. :: +** Pros: Very explicit lifecycle; no shared state. +** Cons: Higher overhead per call and no reuse of compiled classes. +* Provide only low level `CachedCompiler` APIs and no static helper. :: +** Pros: Maximum flexibility for advanced users. +** Cons: Common call sites would need boilerplate and could easily misuse the cache. +Rationale :: +* A shared cached compiler keeps the public API small and satisfies JRC-FN-002 while allowing advanced users to manage their own instances. +* Per class loader caching aligns with application isolation and typical container deployments. +Impact :: +* Most applications rely on the shared `CACHED_COMPILER`; misuse can pin classes for the lifetime of the class loader, so long running systems should treat loader choice carefully. +* Tests must exercise both the shared singleton and user supplied `CachedCompiler` instances, including custom `ClassLoader` paths. +Links :: +* `src/main/java/net/openhft/compiler/CompilerUtils.java` +* `src/main/java/net/openhft/compiler/CachedCompiler.java` +* `src/main/adoc/project-requirements.adoc` (JRC-FN-001 to JRC-FN-005) + +[[RC-NF-P-006]] +=== [RC-NF-P-006] Performance and metaspace budget for cached compilation + +Date :: 2025-11-14 +Context :: +* Requirements JRC-NF-P-006 to JRC-NF-P-008 set limits on compilation latency, steady state invocation overhead, and metaspace growth. +* Initialising `JavaCompiler` and `StandardJavaFileManager` is relatively expensive and must not be repeated unnecessarily. +* Debug output is helpful but can slow down compilation and increase disk activity. +Decision :: +* Reuse a single `JavaCompiler` and `StandardJavaFileManager` across compilation calls via `CompilerUtils.reset()`. +* Maintain a `MyJavaFileManager` per class loader inside `CachedCompiler` to isolate compiled artefacts while still sharing core compiler infrastructure. +* Use a small default option set (`-g`, `-nowarn`) and allow callers to supply additional options when constructing a `CachedCompiler`. +Alternatives :: +* Instantiate a new `JavaCompiler` and file manager for every compilation. :: +** Pros: Simple to reason about; no shared mutable state. +** Cons: Slower start up and higher CPU cost for repeated compiles. +* Disable debug information and warnings by default. :: +** Pros: Slightly faster and smaller class files. +** Cons: Harder to debug issues and reconcile compiler output with source. +Rationale :: +* Reusing compiler infrastructure is the most effective way to keep compile times within the required budget while still supporting rich diagnostics. +* Per class loader file managers help bound metaspace growth and keep compiled classes associated with the correct loader. +Impact :: +* First use of the compiler pays the initialisation cost; subsequent compiles should be significantly faster. +* Long running processes that create many class loaders must still monitor metaspace usage; tests and benchmarks track these behaviours. +Links :: +* `src/main/java/net/openhft/compiler/CompilerUtils.java` +* `src/main/java/net/openhft/compiler/CachedCompiler.java` +* `src/main/adoc/project-requirements.adoc` (JRC-NF-P-006 to JRC-NF-P-008) + +[[RC-RISK-026]] +=== [RC-RISK-026] Debug artefact directory safety + +Date :: 2025-11-14 +Context :: +* Requirement JRC-FN-005 mandates a debug mode that writes `.java` and `.class` files to user supplied directories. +* Requirement JRC-RISK-026 requires a retention policy and safe handling of those directories. +* Without validation a hostile caller could attempt directory traversal using relative paths. +Decision :: +* Treat the configured source and class directories as roots and resolve all debug file paths beneath them using the `safeResolve` helper. +* Reject any path that would escape the configured root directory and throw an `IllegalArgumentException` when traversal is detected. +Alternatives :: +* Write files using the relative paths as supplied without extra checks. :: +** Pros: Simpler implementation. +** Cons: Risk of writing outside the intended directory tree. +* Remove debug file emission from the library. :: +** Pros: Eliminates this class of risk. +** Cons: Makes troubleshooting much harder and violates JRC-FN-005. +Rationale :: +* Safe resolution of paths balances the need for useful debug output with the requirement to keep file writes constrained to explicit directories. +* Failing fast on invalid paths helps surface configuration issues early in development and testing. +Impact :: +* Callers must choose appropriate root directories; attempts to write using paths that escape those roots will fail. +* Future work on retention tooling should build on the same root directory assumptions. +Links :: +* `src/main/java/net/openhft/compiler/CachedCompiler.java` (`safeResolve`) +* `src/main/adoc/project-requirements.adoc` (JRC-FN-005, JRC-RISK-026) diff --git a/src/main/adoc/project-requirements.adoc b/src/main/docs/project-requirements.adoc similarity index 74% rename from src/main/adoc/project-requirements.adoc rename to src/main/docs/project-requirements.adoc index 5e58dfb..b9dc4cb 100644 --- a/src/main/adoc/project-requirements.adoc +++ b/src/main/docs/project-requirements.adoc @@ -1,9 +1,14 @@ = Java Runtime Compiler Project Requirements :toc: :lang: en-GB +:source-highlighter: rouge +:sectnums: == Requirement Catalogue +This document captures all `JRC-*` requirements for the Java Runtime Compiler library using a Nine-Box style tag set grouped by functional, non-functional and testing concerns. +Each identifier links code, decision records and operational guidance back to the same requirement row. + === Functional (FN) JRC-FN-001 :: The library *MUST* compile Java source provided as a `String` and return a `Class` at runtime. @@ -11,19 +16,21 @@ JRC-FN-002 :: The public API *MUST* expose a singleton _cached compiler_ capable JRC-FN-003 :: The library *MUST* support the compilation of nested classes contained in the same source unit. JRC-FN-004 :: Callers *MUST* be able to supply a custom `ClassLoader`; default is the current context loader. JRC-FN-005 :: A _debug mode_ *MUST* emit `.java` and `.class` artefacts to configurable directories for IDE inspection. +* _Decision:_ link:../docs/decision-log.adoc#RC-FN-002[RC-FN-002] (cached compiler API) and link:../docs/decision-log.adoc#RC-RISK-026[RC-RISK-026] (debug artefact safety). -=== Non-Functional – Performance (NF-P) +=== Non-Functional - Performance (NF-P) -JRC-NF-P-006 :: First-time compilation of a <1 kLoC class *SHOULD* complete in ≤ 500 ms on a 3 GHz x86-64 CPU. +JRC-NF-P-006 :: First-time compilation of a <1 kLoC class *SHOULD* complete in <= 500 ms on a 3 GHz x86-64 CPU. JRC-NF-P-007 :: Steady-state invocation latency of compiled methods *MUST* be within 10 % of statically compiled code. JRC-NF-P-008 :: Peak metaspace growth per 1 000 unique dynamic classes *MUST NOT* exceed 50 MB. +* _Decision:_ link:../docs/decision-log.adoc#RC-NF-P-006[RC-NF-P-006] (performance and metaspace budget). -=== Non-Functional – Security (NF-S) +=== Non-Functional - Security (NF-S) JRC-NF-S-009 :: The API *MUST* allow callers to plug in a source-code validator to reject untrusted or malicious input. JRC-NF-S-010 :: Compilation *MUST* occur with the permissions of the hosting JVM; the library supplies _no_ elevated privileges. -=== Non-Functional – Operability (NF-O) +=== Non-Functional - Operability (NF-O) JRC-NF-O-011 :: All internal logging *SHALL* use SLF4J at `INFO` or lower; compilation errors log at `ERROR`. JRC-NF-O-012 :: A health-check helper *SHOULD* verify JDK compiler availability and JVM module flags at start-up. @@ -32,7 +39,8 @@ JRC-NF-O-013 :: The library *MUST* expose a counter metric for successful and fa === Test / QA (TEST) JRC-TEST-014 :: Unit tests *MUST* cover >= 90 % of public API branches, including happy-path and diagnostics. -JRC-TEST-015 :: Concurrency tests *MUST* exercise ≥ 64 parallel compile requests without race or deadlock. +* _Decision:_ link:../docs/decision-log.adoc#RC-TEST-002[RC-TEST-002] (coverage gate alignment). +JRC-TEST-015 :: Concurrency tests *MUST* exercise >= 64 parallel compile requests without race or deadlock. JRC-TEST-016 :: A benchmark suite *SHOULD* publish compile latency and runtime call performance on CI. === Documentation (DOC) From 7891dcb7f3d5d6247955100bf18f509c5da969fd Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Fri, 21 Nov 2025 20:22:35 +0000 Subject: [PATCH 02/13] Refactor CachedCompiler and CompilerUtils for thread safety and performance improvements --- .../net/openhft/compiler/CachedCompiler.java | 21 ++++-- .../net/openhft/compiler/CompilerUtils.java | 67 +++++++++++-------- .../openhft/compiler/MyJavaFileManager.java | 6 +- 3 files changed, 55 insertions(+), 39 deletions(-) diff --git a/src/main/java/net/openhft/compiler/CachedCompiler.java b/src/main/java/net/openhft/compiler/CachedCompiler.java index 4f1c989..a94ff1a 100644 --- a/src/main/java/net/openhft/compiler/CachedCompiler.java +++ b/src/main/java/net/openhft/compiler/CachedCompiler.java @@ -178,16 +178,24 @@ Map compileFromJava(@NotNull String className, String filename = className.replaceAll("\\.", '\\' + File.separator) + ".java"; File file = safeResolve(sourceDir, filename); writeText(file, javaCode); - if (s_standardJavaFileManager == null) - s_standardJavaFileManager = s_compiler.getStandardFileManager(null, null, null); - compilationUnits = s_standardJavaFileManager.getJavaFileObjects(file); + StandardJavaFileManager standardJavaFileManager = s_standardJavaFileManager; + if (standardJavaFileManager == null) { + synchronized (CompilerUtils.class) { + standardJavaFileManager = s_standardJavaFileManager; + if (standardJavaFileManager == null) { + standardJavaFileManager = currentCompiler().getStandardFileManager(null, null, null); + s_standardJavaFileManager = standardJavaFileManager; + } + } + } + compilationUnits = standardJavaFileManager.getJavaFileObjects(file); } else { javaFileObjects.put(className, new JavaSourceFromString(className, javaCode)); compilationUnits = new ArrayList<>(javaFileObjects.values()); // To prevent CME from compiler code } // reuse the same file manager to allow caching of jar files - boolean ok = s_compiler.getTask(writer, fileManager, new DiagnosticListener() { + boolean ok = currentCompiler().getTask(writer, fileManager, new DiagnosticListener() { @Override public void report(Diagnostic diagnostic) { if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { @@ -204,9 +212,8 @@ public void report(Diagnostic diagnostic) { // nothing to return due to compiler error return Collections.emptyMap(); } else { - Map result = fileManager.getAllBuffers(); - return result; + return fileManager.getAllBuffers(); } } @@ -241,7 +248,7 @@ public Class loadFromJava(@NotNull ClassLoader classLoader, MyJavaFileManager fileManager = fileManagerMap.get(classLoader); if (fileManager == null) { - StandardJavaFileManager standardJavaFileManager = s_compiler.getStandardFileManager(null, null, null); + StandardJavaFileManager standardJavaFileManager = currentCompiler().getStandardFileManager(null, null, null); fileManager = getFileManager(standardJavaFileManager); fileManagerMap.put(classLoader, fileManager); } diff --git a/src/main/java/net/openhft/compiler/CompilerUtils.java b/src/main/java/net/openhft/compiler/CompilerUtils.java index 0dd4c6b..b07412c 100644 --- a/src/main/java/net/openhft/compiler/CompilerUtils.java +++ b/src/main/java/net/openhft/compiler/CompilerUtils.java @@ -19,6 +19,8 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.Objects; @@ -41,10 +43,10 @@ public enum CompilerUtils { private static final Logger LOGGER = LoggerFactory.getLogger(CompilerUtils.class); private static final Method DEFINE_CLASS_METHOD; - private static final Charset UTF_8 = Charset.forName("UTF-8"); + private static final Charset UTF_8 = StandardCharsets.UTF_8; private static final String JAVA_CLASS_PATH = "java.class.path"; - static JavaCompiler s_compiler; - static StandardJavaFileManager s_standardJavaFileManager; + static volatile JavaCompiler s_compiler; + static volatile StandardJavaFileManager s_standardJavaFileManager; /* * Use sun.misc.Unsafe to gain access to ClassLoader.defineClass. This allows @@ -79,22 +81,36 @@ private static boolean isDebug() { } /** - * Reinitialises the cached {@link JavaCompiler}. This method is not thread-safe - * and callers must serialise access if used outside static initialisation. + * Reinitialises the cached {@link JavaCompiler}. This method synchronises + * on a dedicated lock to avoid racy lazy initialisation of static fields. * * @throws AssertionError if the compiler classes cannot be loaded. */ private static void reset() { - s_compiler = ToolProvider.getSystemJavaCompiler(); - if (s_compiler == null) { + synchronized (CompilerUtils.class) { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { try { Class javacTool = Class.forName("com.sun.tools.javac.api.JavacTool"); Method create = javacTool.getMethod("create"); - s_compiler = (JavaCompiler) create.invoke(null); + compiler = (JavaCompiler) create.invoke(null); } catch (Exception e) { throw new AssertionError(e); } } + s_compiler = compiler; + // Invalidate any cached file manager tied to the previous compiler. + s_standardJavaFileManager = null; + } + } + + static JavaCompiler currentCompiler() { + JavaCompiler compiler = s_compiler; + if (compiler != null) { + return compiler; + } + reset(); + return s_compiler; } /** @@ -225,11 +241,7 @@ private static String readText(@NotNull String resourceName) throws IOException @NotNull private static String decodeUTF8(@NotNull byte[] bytes) { - try { - return new String(bytes, UTF_8.name()); - } catch (UnsupportedEncodingException e) { - throw new AssertionError(e); - } + return new String(bytes, UTF_8); } @Nullable @@ -240,17 +252,13 @@ private static byte[] readBytes(@NotNull File file) { if (len > Runtime.getRuntime().totalMemory() / 10) throw new IllegalStateException("Attempted to read large file " + file + " was " + len + " bytes."); byte[] bytes = new byte[(int) len]; - DataInputStream dis = null; - try { - dis = new DataInputStream(new FileInputStream(file)); + try (DataInputStream dis = new DataInputStream(Files.newInputStream(file.toPath()))) { dis.readFully(bytes); + return bytes; } catch (IOException e) { - close(dis); LOGGER.warn("Unable to read {}", file, e); throw new IllegalStateException("Unable to read file " + file, e); } - - return bytes; } private static void close(@Nullable Closeable closeable) { @@ -284,11 +292,7 @@ public static boolean writeText(@NotNull File file, @NotNull String text) { */ @NotNull private static byte[] encodeUTF8(@NotNull String text) { - try { - return text.getBytes(UTF_8.name()); - } catch (UnsupportedEncodingException e) { - throw new AssertionError(e); - } + return text.getBytes(UTF_8); } /** @@ -310,7 +314,9 @@ public static boolean writeBytes(@NotNull File file, @NotNull byte[] bytes) { if (Arrays.equals(bytes, bytes2)) return false; bak = new File(parentDir, file.getName() + ".bak"); - file.renameTo(bak); + if (!file.renameTo(bak)) { + LOGGER.debug("Unable to rename {} to backup {}", file, bak); + } } FileOutputStream fos = null; @@ -318,13 +324,16 @@ public static boolean writeBytes(@NotNull File file, @NotNull byte[] bytes) { fos = new FileOutputStream(file); fos.write(bytes); } catch (IOException e) { - close(fos); LOGGER.warn("Unable to write {} as {}", file, decodeUTF8(bytes), e); - file.delete(); - if (bak != null) - bak.renameTo(file); + if (file.exists() && !file.delete()) { + LOGGER.debug("Unable to delete {}", file); + } + if (bak != null && bak.exists() && !bak.renameTo(file)) { + LOGGER.debug("Unable to restore backup {} to {}", bak, file); + } throw new IllegalStateException("Unable to write " + file, e); } finally { + close(fos); if (bak != null && bak.exists() && file.exists()) { if (!bak.delete()) { LOGGER.debug("Unable to delete backup {}", bak); diff --git a/src/main/java/net/openhft/compiler/MyJavaFileManager.java b/src/main/java/net/openhft/compiler/MyJavaFileManager.java index ba788b6..9141697 100644 --- a/src/main/java/net/openhft/compiler/MyJavaFileManager.java +++ b/src/main/java/net/openhft/compiler/MyJavaFileManager.java @@ -31,7 +31,7 @@ */ public class MyJavaFileManager implements JavaFileManager { private static final Logger LOG = LoggerFactory.getLogger(MyJavaFileManager.class); - private final static Unsafe unsafe; + private static final Unsafe unsafe; private static final long OVERRIDE_OFFSET; // Unsafe sets AccessibleObject.override for speed and JDK-9+ compatibility @@ -211,11 +211,11 @@ public Map getAllBuffers() { } catch (InterruptedException t) { Thread.currentThread().interrupt(); - LOG.warn("Interrupted while waiting for compilation result [class=" + e.getKey() + "]"); + LOG.warn("Interrupted while waiting for compilation result [class={}]", e.getKey()); break; } catch (ExecutionException | TimeoutException t) { - LOG.warn("Failed to wait for compilation result [class=" + e.getKey() + "]", t); + LOG.warn("Failed to wait for compilation result [class={}]", e.getKey(), t); continue; } From dfcf92b7cffc9cfb7f3da2793a400dd9ebc4097a Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Fri, 21 Nov 2025 20:22:47 +0000 Subject: [PATCH 03/13] Refactor Foo and FooBarTee classes for improved field visibility and initialization --- src/test/java/eg/FooBarTee.java | 15 ++---- src/test/java/eg/components/Foo.java | 10 ++-- src/test/java/mytest/RuntimeCompileTest.java | 13 ++--- .../compiler/AiRuntimeGuardrailsTest.java | 9 ++-- .../CachedCompilerAdditionalTest.java | 34 ++++++++----- .../net/openhft/compiler/CompilerTest.java | 51 ++++++++++--------- .../openhft/compiler/CompilerUtilsIoTest.java | 25 +++++---- .../net/openhft/compiler/MyIntSupplier.java | 2 +- .../compiler/MyJavaFileManagerTest.java | 6 +-- 9 files changed, 88 insertions(+), 77 deletions(-) diff --git a/src/test/java/eg/FooBarTee.java b/src/test/java/eg/FooBarTee.java index 65123e1..6a40af2 100644 --- a/src/test/java/eg/FooBarTee.java +++ b/src/test/java/eg/FooBarTee.java @@ -8,24 +8,19 @@ import eg.components.TeeImpl; public class FooBarTee { - private final String name; - private final TeeImpl tee; - private final BarImpl bar; - private final BarImpl copy; - public Foo foo; + public final Foo foo; public FooBarTee(String name) { - this.name = name; - tee = new TeeImpl("test"); + TeeImpl tee = new TeeImpl("test"); - bar = new BarImpl(tee, 55); + BarImpl bar = new BarImpl(tee, 55); - copy = new BarImpl(tee, 555); + BarImpl copy = new BarImpl(tee, 555); // ${generatedDate} // Build scripts replace the token with the current date. - foo = new Foo(bar, copy, "generated test ${generatedDate}", 5); + foo = new Foo(bar, copy, "generated test ${generatedDate}", name.length()); } public void start() { diff --git a/src/test/java/eg/components/Foo.java b/src/test/java/eg/components/Foo.java index e379e5d..5ad4a92 100644 --- a/src/test/java/eg/components/Foo.java +++ b/src/test/java/eg/components/Foo.java @@ -3,15 +3,16 @@ */ package eg.components; -@SuppressWarnings("QuestionableName") /** * Simple data holder used to demonstrate dynamic compilation. */ +@SuppressWarnings("QuestionableName") public class Foo { - private final Bar bar; - private final Bar copy; + @SuppressWarnings("unused") + public final Bar bar; + @SuppressWarnings("unused") + public final Bar copy; public final String s; - private final int i; /** * Creates a new instance. @@ -25,6 +26,5 @@ public Foo(Bar bar, Bar copy, String s, int i) { this.bar = bar; this.copy = copy; this.s = s; - this.i = i; } } diff --git a/src/test/java/mytest/RuntimeCompileTest.java b/src/test/java/mytest/RuntimeCompileTest.java index 22b9f0f..13ed6f1 100644 --- a/src/test/java/mytest/RuntimeCompileTest.java +++ b/src/test/java/mytest/RuntimeCompileTest.java @@ -9,6 +9,8 @@ import java.net.URL; import java.net.URLClassLoader; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; @@ -22,7 +24,7 @@ import static org.junit.Assert.fail; public class RuntimeCompileTest { - private static String code = "package mytest;\n" + + private static final String code = "package mytest;\n" + "public class Test implements IntConsumer {\n" + " public void accept(int num) {\n" + " if ((byte) num != num)\n" + @@ -32,7 +34,8 @@ public class RuntimeCompileTest { @Test public void outOfBounds() throws Exception { - ClassLoader cl = new URLClassLoader(new URL[0]); + ClassLoader cl = AccessController.doPrivileged( + (PrivilegedAction) () -> new URLClassLoader(new URL[0])); Class aClass = CompilerUtils.CACHED_COMPILER. loadFromJava(cl, "mytest.Test", code); IntConsumer consumer = (IntConsumer) aClass.getDeclaredConstructor().newInstance(); @@ -41,6 +44,7 @@ public void outOfBounds() throws Exception { consumer.accept(128); // no ok fail(); } catch (IllegalArgumentException expected) { + assertEquals("Unexpected exception type", IllegalArgumentException.class, expected.getClass()); } } @@ -55,10 +59,7 @@ public void testMultiThread() throws Exception { " called.incrementAndGet();\n" + " }\n"); for (int j=0; j<1_000; j++) { - largeClass.append(" public void accept"+j+"(int num) {\n" + - " if ((byte) num != num)\n" + - " throw new IllegalArgumentException();\n" + - " }\n"); + largeClass.append(" public void accept").append(j).append("(int num) {\n").append(" if ((byte) num != num)\n").append(" throw new IllegalArgumentException();\n").append(" }\n"); } largeClass.append("}\n"); final String code2 = largeClass.toString(); diff --git a/src/test/java/net/openhft/compiler/AiRuntimeGuardrailsTest.java b/src/test/java/net/openhft/compiler/AiRuntimeGuardrailsTest.java index 6606fa5..06fdd95 100644 --- a/src/test/java/net/openhft/compiler/AiRuntimeGuardrailsTest.java +++ b/src/test/java/net/openhft/compiler/AiRuntimeGuardrailsTest.java @@ -72,7 +72,7 @@ public void successfulCompilationRecordsMetrics() throws Exception { new CachedCompilerInvoker() ); - Class clazz = pipeline.compile("agent-B", "OkClass", + final Class clazz = pipeline.compile("agent-B", "OkClass", "public class OkClass { public int add(int a, int b) { return a + b; } }"); assertEquals("agent-B should see exactly one attempt", 1, telemetry.compileAttempts("agent-B")); @@ -100,8 +100,8 @@ public void cacheHitDoesNotRecompileButRecordsMetric() throws Exception { ); String source = "public class CacheCandidate { public String id() { return \"ok\"; } }"; - Class first = pipeline.compile("agent-C", "CacheCandidate", source); - Class second = pipeline.compile("agent-C", "CacheCandidate", source); + final Class first = pipeline.compile("agent-C", "CacheCandidate", source); + final Class second = pipeline.compile("agent-C", "CacheCandidate", source); assertEquals("Underlying compiler should only run once thanks to caching", 1, rawCompileCount.get()); assertEquals(2, telemetry.compileAttempts("agent-C")); @@ -109,7 +109,7 @@ public void cacheHitDoesNotRecompileButRecordsMetric() throws Exception { assertEquals(1, telemetry.successes("agent-C")); assertEquals(0, telemetry.compileFailures("agent-C")); assertEquals("Cache hit count should be tracked", 1, telemetry.cacheHits("agent-C")); - assertTrue(first == second); + assertSame(first, second); } @Test @@ -198,6 +198,7 @@ private interface SourceValidator { } private static final class ValidationException extends RuntimeException { + private static final long serialVersionUID = 1L; ValidationException(String message) { super(message); } diff --git a/src/test/java/net/openhft/compiler/CachedCompilerAdditionalTest.java b/src/test/java/net/openhft/compiler/CachedCompilerAdditionalTest.java index 535bc8d..e9889d6 100644 --- a/src/test/java/net/openhft/compiler/CachedCompilerAdditionalTest.java +++ b/src/test/java/net/openhft/compiler/CachedCompilerAdditionalTest.java @@ -19,6 +19,8 @@ import java.util.Comparator; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; +import java.security.AccessController; +import java.security.PrivilegedAction; import static org.junit.Assert.*; @@ -60,8 +62,9 @@ public void compileFromJavaReturnsEmptyMapOnFailure() throws Exception { @Test public void updateFileManagerForClassLoaderInvokesConsumer() throws Exception { CachedCompiler compiler = new CachedCompiler(null, null); - ClassLoader loader = new ClassLoader() { - }; + ClassLoader loader = AccessController.doPrivileged( + (PrivilegedAction) () -> new ClassLoader() { + }); compiler.loadFromJava(loader, "coverage.UpdateTarget", "package coverage; public class UpdateTarget {}"); AtomicBoolean invoked = new AtomicBoolean(false); @@ -73,9 +76,11 @@ public void updateFileManagerForClassLoaderInvokesConsumer() throws Exception { public void updateFileManagerNoOpWhenClassLoaderUnknown() { CachedCompiler compiler = new CachedCompiler(null, null); AtomicBoolean invoked = new AtomicBoolean(false); - compiler.updateFileManagerForClassLoader(new ClassLoader() { - }, fm -> invoked.set(true)); - assertTrue("Consumer should not be invoked when manager missing", !invoked.get()); + ClassLoader loader = AccessController.doPrivileged( + (PrivilegedAction) () -> new ClassLoader() { + }); + compiler.updateFileManagerForClassLoader(loader, fm -> invoked.set(true)); + assertFalse("Consumer should not be invoked when manager missing", invoked.get()); } @Test @@ -86,8 +91,9 @@ public void closeClosesAllManagedFileManagers() throws Exception { AtomicBoolean closed = new AtomicBoolean(false); cachedCompiler.setFileManagerOverride(standard -> new TrackingFileManager(standard, closed)); - ClassLoader loader = new ClassLoader() { - }; + ClassLoader loader = AccessController.doPrivileged( + (PrivilegedAction) () -> new ClassLoader() { + }); cachedCompiler.loadFromJava(loader, "coverage.CloseTarget", "package coverage; public class CloseTarget {}"); cachedCompiler.close(); assertTrue("Close should propagate to file managers", closed.get()); @@ -153,8 +159,9 @@ public void writesSourceAndClassFilesWhenDirectoriesProvided() throws Exception String className = "coverage.FileOutput"; String versionOne = "package coverage; public class FileOutput { public String value() { return \"v1\"; } }"; - ClassLoader loaderOne = new ClassLoader() { - }; + ClassLoader loaderOne = AccessController.doPrivileged( + (PrivilegedAction) () -> new ClassLoader() { + }); firstPass.loadFromJava(loaderOne, className, versionOne); firstPass.close(); @@ -166,16 +173,17 @@ public void writesSourceAndClassFilesWhenDirectoriesProvided() throws Exception CachedCompiler secondPass = new CachedCompiler(sourceDir.toFile(), classDir.toFile()); String versionTwo = "package coverage; public class FileOutput { public String value() { return \"v2\"; } }"; - ClassLoader loaderTwo = new ClassLoader() { - }; + ClassLoader loaderTwo = AccessController.doPrivileged( + (PrivilegedAction) () -> new ClassLoader() { + }); secondPass.loadFromJava(loaderTwo, className, versionTwo); secondPass.close(); byte[] updatedBytes = Files.readAllBytes(classFile); - assertTrue("Updating the source should change emitted bytecode", !Arrays.equals(firstBytes, updatedBytes)); + assertFalse("Updating the source should change emitted bytecode", Arrays.equals(firstBytes, updatedBytes)); Path backupFile = classDir.resolve("coverage/FileOutput.class.bak"); - assertTrue("Backup should be cleaned up", !Files.exists(backupFile)); + assertFalse("Backup should be cleaned up", Files.exists(backupFile)); } finally { deleteRecursively(classDir); deleteRecursively(sourceDir); diff --git a/src/test/java/net/openhft/compiler/CompilerTest.java b/src/test/java/net/openhft/compiler/CompilerTest.java index 011434e..6369c48 100644 --- a/src/test/java/net/openhft/compiler/CompilerTest.java +++ b/src/test/java/net/openhft/compiler/CompilerTest.java @@ -9,12 +9,14 @@ import org.junit.Test; import java.io.*; +import java.nio.charset.StandardCharsets; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.Date; import java.util.List; -import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicBoolean; public class CompilerTest extends TestCase { @@ -40,9 +42,9 @@ public void test_compiler() throws Throwable { // CompilerUtils.setDebug(true); // added so the test passes in Maven. CompilerUtils.addClassPath("target/test-classes"); -// ClassLoader loader = CompilerTest.class.getClassLoader(); -// URLClassLoader urlClassLoader = new URLClassLoader(((URLClassLoader)loader).getURLs(), null); -// Class fooBarTee1 = urlClassLoader.loadClass("eg.FooBarTee"); + // ClassLoader loader = CompilerTest.class.getClassLoader(); + // URLClassLoader urlClassLoader = new URLClassLoader(((URLClassLoader)loader).getURLs(), null); + // Class fooBarTee1 = urlClassLoader.loadClass("eg.FooBarTee"); // this writes the file to disk only when debugging is enabled. CachedCompiler cc = CompilerUtils.DEBUGGING ? @@ -103,10 +105,10 @@ public void test_fromFile() try { System.setOut(new PrintStream(new OutputStream() { @Override - public void write(int b) throws IOException { + public void write(int b) { } - })); - final Constructor stringConstructor = clazz.getConstructor(String.class); + }, true, StandardCharsets.UTF_8.name())); + final Constructor stringConstructor = clazz.getConstructor(String.class); long start = 0; for (int i = -RUNS / 10; i < RUNS; i++) { if (i == 0) start = System.nanoTime(); @@ -134,16 +136,16 @@ public void test_settingPrintStreamWithCompilerErrors() throws Exception { try { System.setOut(new PrintStream(new OutputStream() { @Override - public void write(int b) throws IOException { + public void write(int b) { usedSysOut.set(true); } - })); + }, true, StandardCharsets.UTF_8.name())); System.setErr(new PrintStream(new OutputStream() { @Override - public void write(int b) throws IOException { + public void write(int b) { usedSysErr.set(true); } - })); + }, true, StandardCharsets.UTF_8.name())); CompilerUtils.CACHED_COMPILER.loadFromJava( getClass().getClassLoader(), "TestClass", "clazz TestClass {}", @@ -163,7 +165,7 @@ public void write(int b) throws IOException { "TestClass.java:1: error", "clazz TestClass {}"); for (String expectedError : expectedInErrorFromCompiler) { - String errorMessage = String.format("Does not contain expected '%s' in:\n%s", expectedError, writer.toString()); + String errorMessage = String.format("Does not contain expected '%s' in:%n%s", expectedError, writer); assertTrue(errorMessage, writer.toString().contains(expectedError)); } } @@ -182,13 +184,13 @@ public void test_settingPrintStreamWithNoErrors() throws Exception { public void write(int b) { usedSysOut.set(true); } - })); + }, true, StandardCharsets.UTF_8.name())); System.setErr(new PrintStream(new OutputStream() { @Override - public void write(int b) throws IOException { + public void write(int b) { usedSysErr.set(true); } - })); + }, true, StandardCharsets.UTF_8.name())); CompilerUtils.CACHED_COMPILER.loadFromJava( getClass().getClassLoader(), "TestClass", "class TestClass {}", @@ -214,16 +216,16 @@ public void test_settingPrintStreamWithWarnings() throws Exception { try { System.setOut(new PrintStream(new OutputStream() { @Override - public void write(int b) throws IOException { + public void write(int b) { usedSysOut.set(true); } - })); + }, true, StandardCharsets.UTF_8.name())); System.setErr(new PrintStream(new OutputStream() { @Override - public void write(int b) throws IOException { + public void write(int b) { usedSysErr.set(true); } - })); + }, true, StandardCharsets.UTF_8.name())); CompilerUtils.CACHED_COMPILER.loadFromJava( getClass().getClassLoader(), "TestClass", @@ -242,7 +244,7 @@ public void write(int b) throws IOException { public void test_compilerErrorsDoNotBreakNextCompilations() throws Exception { // quieten the compiler output - PrintWriter quietWriter = new PrintWriter(new StringWriter()); + PrintWriter quietWriter = new PrintWriter(new OutputStreamWriter(new ByteArrayOutputStream(), StandardCharsets.UTF_8)); // cause a compiler error try { @@ -258,7 +260,7 @@ public void test_compilerErrorsDoNotBreakNextCompilations() throws Exception { getClass().getClassLoader(), "S", "class S {" + "public static final String s = \"ok\";}"); - Callable callable = (Callable) + java.util.concurrent.Callable callable = (java.util.concurrent.Callable) CompilerUtils.CACHED_COMPILER.loadFromJava( getClass().getClassLoader(), "OtherClass", "import java.util.concurrent.Callable; " + @@ -274,10 +276,11 @@ public void test_compilerErrorsDoNotBreakNextCompilations() throws Exception { @Test public void testNewCompiler() throws Exception { for (int i = 1; i <= 3; i++) { - ClassLoader classLoader = new ClassLoader() { - }; + ClassLoader classLoader = AccessController.doPrivileged( + (PrivilegedAction) () -> new ClassLoader() { + }); CachedCompiler cc = new CachedCompiler(null, null); - Class a = cc.loadFromJava(classLoader, "A", "public class A { static int i = " + i + "; }"); + cc.loadFromJava(classLoader, "A", "public class A { static int i = " + i + "; }"); Class b = cc.loadFromJava(classLoader, "B", "public class B implements net.openhft.compiler.MyIntSupplier { public int get() { return A.i; } }"); MyIntSupplier bi = (MyIntSupplier) b.getDeclaredConstructor().newInstance(); assertEquals(i, bi.get()); diff --git a/src/test/java/net/openhft/compiler/CompilerUtilsIoTest.java b/src/test/java/net/openhft/compiler/CompilerUtilsIoTest.java index dde885f..48587b6 100644 --- a/src/test/java/net/openhft/compiler/CompilerUtilsIoTest.java +++ b/src/test/java/net/openhft/compiler/CompilerUtilsIoTest.java @@ -12,6 +12,8 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -31,7 +33,7 @@ public void writeTextDetectsNoChangeAndReadBytesMatches() throws Exception { assertTrue("First write should report changes", written); boolean unchanged = CompilerUtils.writeText(file, "hello"); - assertTrue("Repeat write with identical content should be treated as unchanged", !unchanged); + assertFalse("Repeat write with identical content should be treated as unchanged", unchanged); boolean changed = CompilerUtils.writeText(file, "different"); assertTrue("Modified content should trigger a rewrite", changed); @@ -109,7 +111,7 @@ public void defineClassLoadsCompiledBytes() throws Exception { public void addClassPathHandlesMissingDirectory() { Path nonExisting = Paths.get("not-existing-" + System.nanoTime()); boolean result = CompilerUtils.addClassPath(nonExisting.toString()); - assertTrue("Missing directories should return false", !result); + assertFalse("Missing directories should return false", result); } @Test @@ -136,7 +138,7 @@ public void readTextInlineShortcutAndReadBytesMissing() throws Exception { Method readBytes = CompilerUtils.class.getDeclaredMethod("readBytes", File.class); readBytes.setAccessible(true); Object missing = readBytes.invoke(null, new File("definitely-missing-" + System.nanoTime())); - assertEquals(null, missing); + assertNull(missing); Path tempFile = Files.createTempFile("compiler-utils-bytes", ".bin"); Files.write(tempFile, "bytes".getBytes(StandardCharsets.UTF_8)); @@ -165,13 +167,13 @@ public void getInputStreamSupportsInlineContent() throws Exception { Method method = CompilerUtils.class.getDeclaredMethod("getInputStream", String.class); method.setAccessible(true); try (InputStream is = (InputStream) method.invoke(null, "=inline-data")) { - String value = new String(readFully(is)); + String value = new String(readFully(is), StandardCharsets.UTF_8); assertEquals("inline-data", value); } Path tempFile = Files.createTempFile("compiler-utils-stream", ".txt"); Files.write(tempFile, "file-data".getBytes(StandardCharsets.UTF_8)); try (InputStream is = (InputStream) method.invoke(null, tempFile.toString())) { - String value = new String(readFully(is)); + String value = new String(readFully(is), StandardCharsets.UTF_8); assertEquals("file-data", value); } } @@ -190,15 +192,16 @@ public void getInputStreamUsesSlashFallback() throws Exception { Method method = CompilerUtils.class.getDeclaredMethod("getInputStream", String.class); method.setAccessible(true); ClassLoader original = Thread.currentThread().getContextClassLoader(); - ClassLoader loader = new ClassLoader(original) { + ClassLoader loader = AccessController.doPrivileged( + (PrivilegedAction) () -> new ClassLoader(original) { @Override public InputStream getResourceAsStream(String name) { - if ("/fallback-resource".equals(name)) { - return new ByteArrayInputStream("fallback".getBytes(StandardCharsets.UTF_8)); + if ("/fallback-resource".equals(name)) { + return new ByteArrayInputStream("fallback".getBytes(StandardCharsets.UTF_8)); + } + return null; } - return null; - } - }; + }); Thread.currentThread().setContextClassLoader(loader); try (InputStream is = (InputStream) method.invoke(null, "fallback-resource")) { assertEquals("fallback", new String(readFully(is), StandardCharsets.UTF_8)); diff --git a/src/test/java/net/openhft/compiler/MyIntSupplier.java b/src/test/java/net/openhft/compiler/MyIntSupplier.java index dbfa63c..8011ffb 100644 --- a/src/test/java/net/openhft/compiler/MyIntSupplier.java +++ b/src/test/java/net/openhft/compiler/MyIntSupplier.java @@ -7,5 +7,5 @@ * Created by Peter Lawrey on 31/12/2016. */ public interface MyIntSupplier { - public int get(); + int get(); } diff --git a/src/test/java/net/openhft/compiler/MyJavaFileManagerTest.java b/src/test/java/net/openhft/compiler/MyJavaFileManagerTest.java index 693519f..cedb04b 100644 --- a/src/test/java/net/openhft/compiler/MyJavaFileManagerTest.java +++ b/src/test/java/net/openhft/compiler/MyJavaFileManagerTest.java @@ -6,7 +6,6 @@ import org.junit.Test; import javax.tools.FileObject; -import javax.tools.ForwardingJavaFileManager; import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.SimpleJavaFileObject; @@ -61,6 +60,7 @@ public void bufferedClassReturnedFromInput() throws IOException { } } + @SuppressWarnings("rawtypes") @Test public void getJavaFileForInputDelegatesWhenBufferMissing() throws Exception { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); @@ -98,7 +98,7 @@ public InputStream openInputStream() { JavaFileObject result = manager.getJavaFileForInput(StandardLocation.CLASS_OUTPUT, "example.KindMismatch", JavaFileObject.Kind.SOURCE); assertTrue("Delegate should be consulted when buffer missing", delegated.get()); - assertTrue("Result should match delegate outcome", result == expected); + assertSame("Result should match delegate outcome", result, expected); } } @@ -140,7 +140,7 @@ public void listLocationsForModulesAndInferModuleNameDeferToDelegate() throws IO Iterable> locations = manager.listLocationsForModules(modulesLocation); for (Set ignored : locations) { - // no-op + assertNotNull("Module location set should not be null", ignored); } } catch (UnsupportedOperationException ignored) { // Delegate does not expose module support on this JDK. From 9d964ee635dc3dfc50b3e70c096a3b1a9dc5e688 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Fri, 21 Nov 2025 20:22:51 +0000 Subject: [PATCH 04/13] Update AGENTS.md to reflect changes in character set policy and documentation guidelines --- AGENTS.md | 105 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 80 insertions(+), 25 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index afe8075..513d46c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,41 +10,69 @@ LLM-based agents can accelerate development only if they respect our house rules | Requirement | Rationale | |--------------|-----------| -| **British English** spelling (`organisation`, `licence`, *not* `organization`, `license`) except technical US spellings like `synchronized` | Keeps wording consistent with Chronicle's London HQ and existing docs. See the University of Oxford style guide for reference. | -| **ASCII-7 only** (code-points 0-127). Avoid smart quotes, non-breaking spaces and accented characters. | ASCII-7 survives every toolchain Chronicle uses, incl. low-latency binary wire formats that expect the 8th bit to be 0. | -| If a symbol is not available in ASCII-7, use a textual form such as `micro-second`, `>=`, `:alpha:`, `:yes:`. This is the preferred approach and Unicode must not be inserted. | Extended or '8-bit ASCII' variants are *not* portable and are therefore disallowed. | +| **British English** spelling (`organisation`, `licence`, *not* `organization`, `license`) except technical US spellings like `synchronized` | Keeps wording consistent with Chronicle's London HQ and existing docs. See the [University of Oxford style guide](https://www.ox.ac.uk/public-affairs/style-guide) for reference. | +| **ISO-8859-1** (code-points 0-255). Avoid smart quotes, non-breaking spaces and accented characters. | ISO-8859-1 survives every toolchain Chronicle uses. | +| If a symbol is not available in ISO-8859-1, use a textual form such as `>=`, `:alpha:`, `:yes:`. This is the preferred approach and Unicode must not be inserted. | Extended or '8-bit ASCII' variants are *not* portable and are therefore disallowed. | +| Tools to check ASCII compliance include `iconv -f ascii -t ascii` and IDE settings that flag non-ASCII characters. | These help catch stray Unicode characters before code review. | ## Javadoc guidelines **Goal:** Every Javadoc block should add information you cannot glean from the method signature alone. Anything else is noise and slows readers down. -| Do | Don’t | +| Do | Don't | |----|-------| | State *behavioural contracts*, edge-cases, thread-safety guarantees, units, performance characteristics and checked exceptions. | Restate the obvious ("Gets the value", "Sets the name"). | | Keep the first sentence short; it becomes the summary line in aggregated docs. | Duplicate parameter names/ types unless more explanation is needed. | -| Prefer `@param` for *constraints* and `@throws` for *conditions*, following Oracle’s style guide. | Pad comments to reach a line-length target. | +| Prefer `@param` for *constraints* and `@throws` for *conditions*, following Oracle's style guide. | Pad comments to reach a line-length target. | | Remove or rewrite autogenerated Javadoc for trivial getters/setters. | Leave stale comments that now contradict the code. | -The principle that Javadoc should only explain what is *not* manifest from the signature is well-established in the -wider Java community. +The principle that Javadoc should only explain what is *not* manifest from the +signature is well-established in the wider Java community. + +Inline comments should also avoid noise. The following example shows the +difference: + +```java +// BAD: adds no value +int count; // the count + +// GOOD: explains a subtlety +// count of messages pending flush +int count; +``` ## Build & test commands -Agents must verify that the project still compiles and all unit tests pass before opening a PR: +Agents must verify that the project still compiles and all unit tests pass before opening a PR. Running from a clean checkout avoids stale artifacts: ```bash # From repo root -mvn -q verify +mvn -q clean verify ``` +The command should exit with code `0` to indicate success. + +### Quality profiles + +When running static analysis and coverage, prefer the shared Chronicle profiles: + +- From the root aggregator (all modules): `mvn -P quality clean verify` for Checkstyle and SpotBugs, and `mvn -P sonar clean verify` for JaCoCo and SonarCloud integration. +- From this module only (Java 11 or newer): `mvn -P module-quality clean verify` to run SpotBugs for Java-Runtime-Compiler while reusing the shared rules; `mvn checkstyle:check` uses the parent Checkstyle configuration, including tests. ## Commit-message & PR etiquette -1. **Subject line <= 72 chars**, imperative mood: "Fix roll-cycle offset in `ExcerptAppender`". +1. **Subject line <= 72 chars**, imperative mood: Fix roll-cycle offset in `ExcerptAppender`. 2. Reference the JIRA/GitHub issue if it exists. 3. In *body*: *root cause -> fix -> measurable impact* (latency, allocation, etc.). Use ASCII bullet points. 4. **Run `mvn verify`** again after rebasing. +### When to open a PR + +* Open a pull request once your branch builds and tests pass with `mvn -q clean verify`. +* Link the PR to the relevant issue or decision record. +* Keep PRs focused: avoid bundling unrelated refactoring with new features. +* Re-run the build after addressing review comments to ensure nothing broke. + ## What to ask the reviewers * *Is this AsciiDoc documentation precise enough for a clean-room re-implementation?* @@ -53,10 +81,18 @@ mvn -q verify * Does the commit point back to the relevant requirement or decision tag? * Would an example or small diagram help future maintainers? +### Security checklist (review **after every change**) + +**Run a security review on *every* PR**: Walk through the diff looking for input validation, authentication, authorisation, encoding/escaping, overflow, resource exhaustion and timing-attack issues. + +**Never commit secrets or credentials**: tokens, passwords, private keys, TLS materials, internal hostnames, Use environment variables, HashiCorp Vault, AWS/GCP Secret Manager, etc. + +**Document security trade-offs**: Chronicle prioritises low-latency systems; sometimes we relax safety checks for specific reasons. Future maintainers must find these hot-spots quickly, In Javadoc and `.adoc` files call out *why* e.g. "Unchecked cast for performance - assumes trusted input". + ## Project requirements -See the [Decision Log](src/main/adoc/decision-log.adoc) for the latest project decisions. -See the [Project Requirements](src/main/adoc/project-requirements.adoc) for details on project requirements. +See the [Decision Log](src/main/docs/decision-log.adoc) for the latest project decisions. +See the [Project Requirements](src/main/docs/project-requirements.adoc) for details on project requirements. ## Elevating the Workflow with Real-Time Documentation @@ -84,7 +120,7 @@ This tight loop informs the AI accurately and creates immediate clarity for all When using AI agents to assist with development, please adhere to the following guidelines: -* **Respect the Language & Character-set Policy**: Ensure all AI-generated content follows the British English and ASCII-7 guidelines outlined above. +* **Respect the Language & Character-set Policy**: Ensure all AI-generated content follows the British English and ISO-8859-1 guidelines outlined above. Focus on Clarity: AI-generated documentation should be clear and concise and add value beyond what is already present in the code or existing documentation. * **Avoid Redundancy**: Do not generate content that duplicates existing documentation or code comments unless it provides additional context or clarification. * **Review AI Outputs**: Always review AI-generated content for accuracy, relevance, and adherence to the project's documentation standards before committing it to the repository. @@ -118,13 +154,12 @@ To improve traceability, we adopt the Nine-Box taxonomy for requirement and deci ```asciidoc === [Identifier] Title of Decision -- Date: YYYY-MM-DD -- Context: +Date :: YYYY-MM-DD +Context :: * What is the issue that this decision addresses? * What are the driving forces, constraints, and requirements? -- Decision Statement: -* What is the change that is being proposed or was decided? -- **Alternatives Considered:** +Decision Statement :: What is the change that is being proposed or was decided? +Alternatives Considered :: * [Alternative 1 Name/Type]: ** *Description:* Brief description of the alternative. ** *Pros:* ... @@ -133,14 +168,14 @@ To improve traceability, we adopt the Nine-Box taxonomy for requirement and deci ** *Description:* Brief description of the alternative. ** *Pros:* ... ** *Cons:* ... -- **Rationale for Decision:** +Rationale for Decision :: * Why was the chosen decision selected? * How does it address the context and outweigh the cons of alternatives? -- **Impact & Consequences:** +Impact & Consequences :: * What are the positive and negative consequences of this decision? * How does this decision affect the system, developers, users, or operations? - What are the trade-offs made? -- **Notes/Links:** +Notes/Links :: ** (Optional: Links to relevant issues, discussions, documentation, proof-of-concepts) ``` @@ -151,11 +186,31 @@ To improve traceability, we adopt the Nine-Box taxonomy for requirement and deci Do not rely on indentation for list items in AsciiDoc documents. Use the following pattern instead: ```asciidoc -- top level -* second level - ** third level +section :: Top Level Section (Optional) +* first level + ** nested level ``` ### Emphasis and Bold Text -In AsciiDoc, an underscore `_` is _emphasis_; `*text*` is *bold*. \ No newline at end of file +In AsciiDoc, an underscore `_` is _emphasis_; `*text*` is *bold*. + +### Section Numbering + +Use automatic section numbering for all `.adoc` files. + +* Add `:sectnums:` to the document header. +* Do not prefix section titles with manual numbers to avoid duplication. + +```asciidoc += Document Title +Chronicle Software +:toc: +:sectnums: +:lang: en-GB +:source-highlighter: rouge + +The document overview goes here. + +== Section 1 Title +``` From 541bd309d14b82c0872561233760323d365b833e Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Fri, 21 Nov 2025 20:22:57 +0000 Subject: [PATCH 05/13] Update third-party-bom version to 3.27ea7 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5c5868c..7996932 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ net.openhft third-party-bom - 3.27ea5 + 3.27ea7 pom import From a51b6d5201a8e3591bc39b7e29f7ac7c712da883 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Fri, 14 Nov 2025 15:09:03 +0000 Subject: [PATCH 06/13] Enhance documentation with British English conventions and formatting updates --- AGENTS.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 513d46c..3ba1358 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,5 +1,12 @@ # Guidance for AI agents, bots, and humans contributing to Chronicle Software's OpenHFT projects. +- Follow repository `AGENTS.md` for the base rules; this file adds Java-Runtime-Compiler specifics. Durable docs live in `src/main/docs/` with the landing page at `README.adoc`. +- Purpose: compile plain Java source strings at runtime and load classes; used for dynamic logic injection and code generation pipelines. +- Build commands: full build `mvn -q clean verify`; module-only without tests `mvn -pl Java-Runtime-Compiler -am -DskipTests install`. +- Quality gates: keep Checkstyle/SpotBugs clean; avoid unsafe classloader leaks; ensure generated classes are closed/evicted as documented. +- Documentation: maintain Nine-Box IDs in `src/main/docs/project-requirements.adoc` and link decisions/tests to them; British English and ASCII/ISO-8859-1 with `:source-highlighter: rouge`. +- Guardrails: treat generated code as untrusted; enforce validation and sandboxing controls described in `src/main/docs/ai-runtime-guardrails.adoc` / `ai-validator-spec.adoc`; call out any security-impacting configuration changes. + LLM-based agents can accelerate development only if they respect our house rules. This file tells you: * how to run and verify the build; @@ -57,7 +64,6 @@ The command should exit with code `0` to indicate success. When running static analysis and coverage, prefer the shared Chronicle profiles: - From the root aggregator (all modules): `mvn -P quality clean verify` for Checkstyle and SpotBugs, and `mvn -P sonar clean verify` for JaCoCo and SonarCloud integration. -- From this module only (Java 11 or newer): `mvn -P module-quality clean verify` to run SpotBugs for Java-Runtime-Compiler while reusing the shared rules; `mvn checkstyle:check` uses the parent Checkstyle configuration, including tests. ## Commit-message & PR etiquette From d4c3d38572de90dd967b5518f803dc327dab6661 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Mon, 17 Nov 2025 14:02:08 +0000 Subject: [PATCH 07/13] Apply QUALITY_PLAYBOOK to Java-Runtime-Compiler --- pom.xml | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/pom.xml b/pom.xml index 7996932..58d0e12 100644 --- a/pom.xml +++ b/pom.xml @@ -140,6 +140,18 @@ + + + org.apache.maven.plugins + maven-checkstyle-plugin + + ${checkstyle.config.location} + true + true + true + ${checkstyle.violationSeverity} + + @@ -173,6 +185,36 @@ + + module-quality + + [11,) + + + + + com.github.spotbugs + spotbugs-maven-plugin + 4.9.8.1 + + Max + Low + true + true + + + + spotbugs-main + process-classes + + spotbugs + + + + + + + scm:git:git@github.com:OpenHFT/Java-Runtime-Compiler.git From e2b1dd6bceff8c43fc08db1813e9875cc76a390b Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Tue, 18 Nov 2025 13:12:48 +0000 Subject: [PATCH 08/13] Checkpoint --- .../java/net/openhft/compiler/CompilerUtils.java | 13 +++++++------ .../java/net/openhft/compiler/CompilerTest.java | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/openhft/compiler/CompilerUtils.java b/src/main/java/net/openhft/compiler/CompilerUtils.java index b07412c..8e9e2ac 100644 --- a/src/main/java/net/openhft/compiler/CompilerUtils.java +++ b/src/main/java/net/openhft/compiler/CompilerUtils.java @@ -22,6 +22,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Objects; @@ -90,14 +91,14 @@ private static void reset() { synchronized (CompilerUtils.class) { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); if (compiler == null) { - try { - Class javacTool = Class.forName("com.sun.tools.javac.api.JavacTool"); - Method create = javacTool.getMethod("create"); + try { + Class javacTool = Class.forName("com.sun.tools.javac.api.JavacTool"); + Method create = javacTool.getMethod("create"); compiler = (JavaCompiler) create.invoke(null); - } catch (Exception e) { - throw new AssertionError(e); + } catch (Exception e) { + throw new AssertionError(e); + } } - } s_compiler = compiler; // Invalidate any cached file manager tied to the previous compiler. s_standardJavaFileManager = null; diff --git a/src/test/java/net/openhft/compiler/CompilerTest.java b/src/test/java/net/openhft/compiler/CompilerTest.java index 6369c48..1cbbfcd 100644 --- a/src/test/java/net/openhft/compiler/CompilerTest.java +++ b/src/test/java/net/openhft/compiler/CompilerTest.java @@ -108,7 +108,7 @@ public void test_fromFile() public void write(int b) { } }, true, StandardCharsets.UTF_8.name())); - final Constructor stringConstructor = clazz.getConstructor(String.class); + final Constructor stringConstructor = clazz.getConstructor(String.class); long start = 0; for (int i = -RUNS / 10; i < RUNS; i++) { if (i == 0) start = System.nanoTime(); From 5ea1fcdf4e03ac695b03e58c3e8405056405278c Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Mon, 24 Nov 2025 10:22:42 +0000 Subject: [PATCH 09/13] Remove unnecessary blank lines in various classes for improved code readability --- LICENSE.adoc | 3 +++ README.adoc | 9 +++++++-- src/main/docs/decision-log.adoc | 9 ++++----- src/main/docs/project-requirements.adoc | 8 ++++---- src/main/java/net/openhft/compiler/CachedCompiler.java | 1 - .../net/openhft/compiler/JavaSourceFromString.java | 10 +++++----- src/test/java/eg/components/BarImpl.java | 1 - 7 files changed, 23 insertions(+), 18 deletions(-) diff --git a/LICENSE.adoc b/LICENSE.adoc index eb12fcc..6d68b90 100644 --- a/LICENSE.adoc +++ b/LICENSE.adoc @@ -1,5 +1,8 @@ == Copyright 2016-2025 chronicle.software +:toc: +:lang: en-GB +:source-highlighter: rouge Licensed under the *Apache License, Version 2.0* (the "License"); you may not use this file except in compliance with the License. diff --git a/README.adoc b/README.adoc index 2dfaae2..f74539e 100644 --- a/README.adoc +++ b/README.adoc @@ -1,8 +1,13 @@ = Chronicle Runtime Compiler +:toc: +:lang: en-GB +:source-highlighter: rouge Chronicle Software -:css-signature: demo -:toc: macro +:toc: :sectnums: +:toc: macro +:lang: en-GB +:css-signature: demo :source-highlighter: rouge image:https://maven-badges.herokuapp.com/maven-central/net.openhft/compiler/badge.svg[] diff --git a/src/main/docs/decision-log.adoc b/src/main/docs/decision-log.adoc index 8787d11..7f3aedc 100644 --- a/src/main/docs/decision-log.adoc +++ b/src/main/docs/decision-log.adoc @@ -1,5 +1,4 @@ = Java Runtime Compiler Decision Log -Chronicle Software :toc: :sectnums: :lang: en-GB @@ -55,7 +54,7 @@ Each entry uses the Nine-Box tag set and links back to `project-requirements.ado ** Documentation for requirement JRC-TEST-014 is updated to the same value. * Notes/Links: ** Thresholds maintained in `pom.xml`. -** Updated requirement: `src/main/adoc/project-requirements.adoc` (JRC-TEST-014). +** Updated requirement: `src/main/docs/project-requirements.adoc` (JRC-TEST-014). [[RC-FN-002]] === [RC-FN-002] Cached compiler API and custom class loaders @@ -84,7 +83,7 @@ Impact :: Links :: * `src/main/java/net/openhft/compiler/CompilerUtils.java` * `src/main/java/net/openhft/compiler/CachedCompiler.java` -* `src/main/adoc/project-requirements.adoc` (JRC-FN-001 to JRC-FN-005) +* `src/main/docs/project-requirements.adoc` (JRC-FN-001 to JRC-FN-005) [[RC-NF-P-006]] === [RC-NF-P-006] Performance and metaspace budget for cached compilation @@ -114,7 +113,7 @@ Impact :: Links :: * `src/main/java/net/openhft/compiler/CompilerUtils.java` * `src/main/java/net/openhft/compiler/CachedCompiler.java` -* `src/main/adoc/project-requirements.adoc` (JRC-NF-P-006 to JRC-NF-P-008) +* `src/main/docs/project-requirements.adoc` (JRC-NF-P-006 to JRC-NF-P-008) [[RC-RISK-026]] === [RC-RISK-026] Debug artefact directory safety @@ -142,4 +141,4 @@ Impact :: * Future work on retention tooling should build on the same root directory assumptions. Links :: * `src/main/java/net/openhft/compiler/CachedCompiler.java` (`safeResolve`) -* `src/main/adoc/project-requirements.adoc` (JRC-FN-005, JRC-RISK-026) +* `src/main/docs/project-requirements.adoc` (JRC-FN-005, JRC-RISK-026) diff --git a/src/main/docs/project-requirements.adoc b/src/main/docs/project-requirements.adoc index b9dc4cb..44253c0 100644 --- a/src/main/docs/project-requirements.adoc +++ b/src/main/docs/project-requirements.adoc @@ -1,8 +1,8 @@ = Java Runtime Compiler Project Requirements :toc: +:sectnums: :lang: en-GB :source-highlighter: rouge -:sectnums: == Requirement Catalogue @@ -16,14 +16,14 @@ JRC-FN-002 :: The public API *MUST* expose a singleton _cached compiler_ capable JRC-FN-003 :: The library *MUST* support the compilation of nested classes contained in the same source unit. JRC-FN-004 :: Callers *MUST* be able to supply a custom `ClassLoader`; default is the current context loader. JRC-FN-005 :: A _debug mode_ *MUST* emit `.java` and `.class` artefacts to configurable directories for IDE inspection. -* _Decision:_ link:../docs/decision-log.adoc#RC-FN-002[RC-FN-002] (cached compiler API) and link:../docs/decision-log.adoc#RC-RISK-026[RC-RISK-026] (debug artefact safety). +* _Decision:_ link:decision-log.adoc#RC-FN-002[RC-FN-002] (cached compiler API) and link:decision-log.adoc#RC-RISK-026[RC-RISK-026] (debug artefact safety). === Non-Functional - Performance (NF-P) JRC-NF-P-006 :: First-time compilation of a <1 kLoC class *SHOULD* complete in <= 500 ms on a 3 GHz x86-64 CPU. JRC-NF-P-007 :: Steady-state invocation latency of compiled methods *MUST* be within 10 % of statically compiled code. JRC-NF-P-008 :: Peak metaspace growth per 1 000 unique dynamic classes *MUST NOT* exceed 50 MB. -* _Decision:_ link:../docs/decision-log.adoc#RC-NF-P-006[RC-NF-P-006] (performance and metaspace budget). +* _Decision:_ link:decision-log.adoc#RC-NF-P-006[RC-NF-P-006] (performance and metaspace budget). === Non-Functional - Security (NF-S) @@ -39,7 +39,7 @@ JRC-NF-O-013 :: The library *MUST* expose a counter metric for successful and fa === Test / QA (TEST) JRC-TEST-014 :: Unit tests *MUST* cover >= 90 % of public API branches, including happy-path and diagnostics. -* _Decision:_ link:../docs/decision-log.adoc#RC-TEST-002[RC-TEST-002] (coverage gate alignment). +* _Decision:_ link:decision-log.adoc#RC-TEST-002[RC-TEST-002] (coverage gate alignment). JRC-TEST-015 :: Concurrency tests *MUST* exercise >= 64 parallel compile requests without race or deadlock. JRC-TEST-016 :: A benchmark suite *SHOULD* publish compile latency and runtime call performance on CI. diff --git a/src/main/java/net/openhft/compiler/CachedCompiler.java b/src/main/java/net/openhft/compiler/CachedCompiler.java index a94ff1a..9a5fc9e 100644 --- a/src/main/java/net/openhft/compiler/CachedCompiler.java +++ b/src/main/java/net/openhft/compiler/CachedCompiler.java @@ -217,7 +217,6 @@ public void report(Diagnostic diagnostic) { } } - /** * Compile and load using a specific class loader and writer. The * compilation result is cached against the loader for future calls. diff --git a/src/main/java/net/openhft/compiler/JavaSourceFromString.java b/src/main/java/net/openhft/compiler/JavaSourceFromString.java index 49cf37f..9ced010 100644 --- a/src/main/java/net/openhft/compiler/JavaSourceFromString.java +++ b/src/main/java/net/openhft/compiler/JavaSourceFromString.java @@ -8,11 +8,11 @@ import javax.tools.SimpleJavaFileObject; import java.net.URI; -/* - * An internal SimpleJavaFileObject implementation representing Java source - * code provided as a String, allowing the Java compiler to read source - * directly from memory. Example URI: string:///com/example/Hello.java. The - * contents are expected to be UTF-8. +/** + * {@link javax.tools.JavaFileObject} backed by a String of source code. + *

+ * Allows the JDK compiler to consume in-memory source via a synthetic URI such as + * {@code string:///com/example/Hello.java}, avoiding the need for temporary files. */ class JavaSourceFromString extends SimpleJavaFileObject { /** diff --git a/src/test/java/eg/components/BarImpl.java b/src/test/java/eg/components/BarImpl.java index 40e34a0..c004ea6 100644 --- a/src/test/java/eg/components/BarImpl.java +++ b/src/test/java/eg/components/BarImpl.java @@ -6,7 +6,6 @@ /** * Sample implementation used for tests. */ - public class BarImpl implements Bar { private final int i; private final Tee tee; From 7fd55b98ae495864bc6f898f7e4d1710c6f5b4cf Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Mon, 24 Nov 2025 10:35:55 +0000 Subject: [PATCH 10/13] Remove unnecessary blank lines in various classes for improved code readability --- TODO.md | 262 ++++ effective-pom.xml | 1352 +++++++++++++++++ .../net/openhft/compiler/package-info.java | 8 + 3 files changed, 1622 insertions(+) create mode 100644 TODO.md create mode 100644 effective-pom.xml create mode 100644 src/main/java/net/openhft/compiler/package-info.java diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..0a54a95 --- /dev/null +++ b/TODO.md @@ -0,0 +1,262 @@ +# Java-Runtime-Compiler - Repository TODO + +**📋 Part of:** [Chronicle Architecture Documentation](../ARCH_TODO.md) +**Module Layer:** Infrastructure (Compilation) +**Priority:** 🟣 P5 +**Last Updated:** 2025-11-16 + +## Purpose + +This TODO file tracks work specific to Java-Runtime-Compiler that feeds into the master [ARCH_TODO.md](../ARCH_TODO.md). It helps break down the architecture documentation work into manageable, repository-specific chunks. + +## Related Main TODO Files + +- [../ARCH_TODO.md](../ARCH_TODO.md) - Master architecture documentation roadmap +- [../TODO_INDEX.md](../TODO_INDEX.md) - Index of all TODO files +- [../ADOC_TODO.md](../ADOC_TODO.md) - AsciiDoc standardization (affects this module) + +## Module Information for Architecture Overview + +### Basic Information +- [x] **Module Name:** Java-Runtime-Compiler +- [x] **Maven Artifact ID:** java-runtime-compiler +- [ ] [P2] [E:S] **Primary Purpose:** [1-2 sentence description] +- [ ] [P2] [E:S] **Layer in Chronicle Stack:** Infrastructure (Compilation) +- [ ] [P2] [E:M] **Dependencies (Chronicle modules):** [List key Chronicle dependencies] +- [ ] [P2] [E:M] **Key Classes/Interfaces:** [List 3-5 most important public APIs] + +### ISO Alignment and Trust Zone + +- [x] **Trust zone identified (Edge/Core/Foundation):** Java-Runtime-Compiler is a *Foundation (Zone C)* module providing runtime code-generation capabilities used by other Chronicle libraries. +- [x] **Shared standards reviewed:** Align its docs with the shared architectural and security standards in `Chronicle-Quality-Rules/src/main/docs`, paying particular attention to how dynamically generated code is controlled and tested. + +### Architecture Information for ARCH_TODO.md Stage 3 + +**Feeds into:** ARCH_TODO.md Stage 3 - Module Deep Dives (ARCH-MOD-JRC) + +- [ ] [P2] [E:M] **Core Abstractions:** [List primary abstractions this module provides] +- [ ] [P2] [E:M] **Interactions with other modules:** [Which Chronicle modules does this use/integrate with?] +- [ ] [P2] [E:M] **Typical use cases:** [List 2-3 common scenarios where this module is used] +- [ ] [P2] [E:M] **Performance characteristics:** [Key performance metrics if applicable] +- [ ] [P2] [E:M] **Design patterns used:** [e.g., flyweight, single writer, etc.] + +### Existing Documentation Audit + +- [ ] [P2] [E:M] Check if `src/main/docs/architecture-overview.adoc` exists + - [ ] [P2] [E:L] If yes: Review quality (compare to Chronicle-Bytes standard) + - [ ] [P2] [E:S] If no: Note as gap for ARCH_TODO Stage 5.5 +- [ ] [P2] [E:M] Check if `src/main/docs/project-requirements.adoc` exists + - [ ] [P2] [E:L] If yes: Review for ARCH_TODO Stage 1.75 (Requirements Overview) + - [ ] [P2] [E:S] If no: Note as gap for FUNC_TODO.md +- [ ] [P2] [E:M] Check if `src/main/docs/decision-log.adoc` exists + - [ ] [P2] [E:L] If yes: Review for ARCH_TODO Stage 1.85 (Decision Log Overview) + - [ ] [P2] [E:S] If no: Note as gap for DECISION_TODO.md +- [ ] [P1] [E:M] Check if `README.adoc` provides good module overview +- [ ] [P1] [E:S] Check if `AGENTS.md` exists and follows canonical template + +### Documentation Gaps (for ARCH_TODO Stage 5.5) + +**Missing Documentation:** +- [ ] [P1] [E:S] Architecture overview? [Y/N] +- [ ] [P1] [E:S] Requirements documentation? [Y/N] +- [ ] [P1] [E:S] Decision log? [Y/N] +- [ ] [P1] [E:S] Security review? [Y/N] +- [ ] [P1] [E:S] Testing strategy? [Y/N] +- [ ] [P1] [E:S] Performance targets? [Y/N] + +**Documentation Quality Issues:** +- [ ] [P2] [E:M] Missing `:toc:`, `:lang: en-GB`, or `:source-highlighter: rouge`? +- [ ] [P2] [E:M] Manual section numbering instead of `:sectnums:`? +- [ ] [P2] [E:M] Broken cross-references? +- [ ] [P2] [E:M] Outdated information? + +## Requirements for Architecture Overview (ARCH_TODO Stage 1.75) + +**Feeds into:** Requirements Overview consolidation + +- [ ] [P1] [E:L] **Identify key functional requirements:** [List 3-5 most important] +- [ ] [P1] [E:L] **Identify key non-functional requirements:** + - [ ] [P1] [E:M] Performance targets: [e.g., latency, throughput] + - [ ] [P1] [E:M] Security obligations: [e.g., bounds checking, input validation] + - [ ] [P1] [E:M] Operability requirements: [e.g., monitoring, logging] +- [ ] [P2] [E:L] **Map requirements to architecture patterns:** [How do requirements drive design?] + +## Decisions for Architecture Overview (ARCH_TODO Stage 1.85) + +**Feeds into:** Decision Log Overview consolidation + +- [ ] [P1] [E:L] **Identify key architectural decisions:** [List 2-4 major decisions] + - [ ] [P1] [E:S] Decision ID (if in decision-log.adoc): + - [ ] [P1] [E:S] Brief description: + - [ ] [P1] [E:M] Rationale: + - [ ] [P1] [E:M] Alternatives considered: +- [ ] [P2] [E:L] **Identify decision patterns used:** + - [ ] [P2] [E:M] Off-heap memory? [Y/N - explain] + - [ ] [P2] [E:M] Single writer principle? [Y/N - explain] + - [ ] [P2] [E:M] Reference counting? [Y/N - explain] + - [ ] [P2] [E:M] Flyweight pattern? [Y/N - explain] + +## Glossary Terms (ARCH_TODO Stage 1.5) + +**Feeds into:** Cross-module glossary + +- [ ] [P3] [E:M] **Module-specific terms to include in glossary:** + - [ ] [P3] [E:S] Term 1: [Definition] + - [ ] [P3] [E:S] Term 2: [Definition] + - [ ] [P3] [E:S] [Add more as needed] + +## ISO 9001 Quality Management Considerations + +**Reference:** [../COMPLIANCE_QUICK_REFERENCE.md](../COMPLIANCE_QUICK_REFERENCE.md) + +### Design Inputs (ISO 9001 Clause 8.3.3) +- [ ] [P1] [E:L] **Functional requirements documented?** + - [ ] [P1] [E:M] Location: `src/main/docs/project-requirements.adoc` + - [ ] [P1] [E:M] Requirements use Nine-Box taxonomy? (JRC-FN-NNN) + - [ ] [P1] [E:M] Requirements are testable and verifiable? +- [ ] [P1] [E:L] **Non-functional requirements documented?** + - [ ] [P1] [E:M] Performance requirements (JRC-NF-P-NNN) + - [ ] [P1] [E:M] Security requirements (JRC-NF-S-NNN) + - [ ] [P1] [E:M] Operability requirements (JRC-NF-O-NNN) + +### Design Outputs (ISO 9001 Clause 8.3.5) +- [ ] [P1] [E:L] **Architecture documented?** + - [ ] [P1] [E:M] Location: `src/main/docs/architecture-overview.adoc` + - [ ] [P1] [E:M] Describes key components and their interactions? + - [ ] [P1] [E:M] Includes interface specifications? +- [ ] [P1] [E:L] **APIs and interfaces specified?** + - [ ] [P1] [E:M] Public API documented (JavaDoc)? + - [ ] [P1] [E:M] Integration points with other modules described? + +### Design Verification (ISO 9001 Clause 8.3.4) +- [ ] [P1] [E:L] **Requirements traceable to tests?** + - [ ] [P1] [E:M] Test classes reference requirement IDs in comments/docs? + - [ ] [P1] [E:M] Coverage: What % of requirements have corresponding tests? +- [ ] [P1] [E:L] **Test strategy documented?** + - [ ] [P1] [E:M] Unit test approach + - [ ] [P1] [E:M] Integration test approach + - [ ] [P1] [E:M] Performance test approach (if applicable) +- [ ] [P1] [E:L] **Code review evidence?** + - [ ] [P1] [E:M] PR review process followed? + - [ ] [P1] [E:M] Review comments addressed? + +### Design Changes (ISO 9001 Clause 8.3.4) +- [ ] [P1] [E:L] **Architectural decisions documented?** + - [ ] [P1] [E:M] Location: `src/main/docs/decision-log.adoc` + - [ ] [P1] [E:M] Decisions include context, alternatives, rationale? + - [ ] [P1] [E:M] Impact of changes assessed? +- [ ] [P1] [E:L] **Change history maintained?** + - [ ] [P1] [E:M] Git commit messages describe rationale? + - [ ] [P1] [E:M] Breaking changes documented in release notes? + +## ISO 27001 Information Security Considerations + +**Reference:** [../ARCHITECTURE_RESEARCH_GUIDE.md](../ARCHITECTURE_RESEARCH_GUIDE.md) - Security Research Topics + +### Secure Coding (ISO 27001 Control A.8.28) +- [ ] [P1] [E:XL] **Input validation implemented?** + - [ ] [P1] [E:M] Where are untrusted inputs received? [List entry points] + - [ ] [P1] [E:M] How are malformed inputs handled? + - [ ] [P1] [E:S] Size limits enforced? +- [ ] [P1] [E:XL] **Bounds checking implemented?** + - [ ] [P1] [E:M] Buffer overflow prevention mechanisms? + - [ ] [P1] [E:M] Array access validation? + - [ ] [P1] [E:M] Off-heap memory bounds checked? +- [ ] [P1] [E:L] **Static analysis performed?** + - [ ] [P1] [E:M] Checkstyle violations reviewed? + - [ ] [P1] [E:M] SpotBugs security patterns checked? + - [ ] [P1] [E:M] Suppressions justified and documented? + +### Access Control (ISO 27001 Control A.8.3) +- [ ] [P1] [E:L] **Access restrictions implemented?** + - [ ] [P1] [E:M] Are there authentication/authorization mechanisms? [Y/N] + - [ ] [P1] [E:M] If yes, where and how are they implemented? + - [ ] [P1] [E:M] Principle of least privilege followed? +- [ ] [P1] [E:L] **Privileged operations identified?** + - [ ] [P1] [E:M] Which operations require elevated privileges? + - [ ] [P1] [E:M] How are they protected? + +### Cryptographic Controls (ISO 27001 Control A.8.24) +- [ ] [P1] [E:L] **Cryptography usage identified?** + - [ ] [P1] [E:M] Is encryption used? [Y/N - where?] + - [ ] [P1] [E:M] Is hashing used? [Y/N - which algorithms?] + - [ ] [P1] [E:M] Is TLS/SSL used? [Y/N - configuration?] +- [ ] [P1] [E:L] **Key management?** + - [ ] [P1] [E:M] How are cryptographic keys managed? + - [ ] [P1] [E:M] Are keys hardcoded? [Y/N - if yes, flag as risk] + +### Network Security (ISO 27001 Control A.8.22) +- [ ] [P1] [E:L] **Network communication security?** + - [ ] [P1] [E:M] Does this module communicate over network? [Y/N] + - [ ] [P1] [E:M] If yes, is communication encrypted? + - [ ] [P1] [E:M] How are network endpoints authenticated? +- [ ] [P1] [E:L] **Network configuration?** + - [ ] [P1] [E:M] Secure defaults configured? + - [ ] [P1] [E:M] Insecure protocols disabled? + +### Vulnerability Management (ISO 27001 Control A.8.8) +- [ ] [P1] [E:L] **Known vulnerabilities?** + - [ ] [P1] [E:M] Any open security issues in GitHub? + - [ ] [P1] [E:M] Any CVEs against dependencies? +- [ ] [P1] [E:L] **Security testing?** + - [ ] [P1] [E:M] Fuzz testing performed? + - [ ] [P1] [E:M] Security-specific test cases? + - [ ] [P1] [E:M] Penetration testing performed? + +### Security Documentation +- [ ] [P1] [E:L] **Security review documented?** + - [ ] [P1] [E:M] Location: `src/main/docs/security-review.adoc` + - [ ] [P1] [E:M] Threat model documented? + - [ ] [P1] [E:M] Security controls described? + - [ ] [P1] [E:M] Known limitations documented? + +## Improvement Tasks (ARCH_TODO Stage 5.5) + +**Feeds into:** Improve Existing Module Documentation + +### High Priority +- [ ] [P1] [E:L] Create missing architecture-overview.adoc (if needed) +- [ ] [P1] [E:M] Add missing front-matter to existing docs +- [ ] [P1] [E:M] Fix broken cross-references +- [ ] [P1] [E:S] Add `:sectnums:` where appropriate + +### Medium Priority +- [ ] [P2] [E:L] Expand brief architecture docs (if < 75 lines) +- [ ] [P2] [E:L] Add "Trade-offs and Alternatives" section (following Chronicle-Bytes pattern) +- [ ] [P2] [E:M] Add performance characteristics section +- [ ] [P2] [E:M] Create decision log entries for undocumented decisions + +### Low Priority +- [ ] [P3] [E:L] Add diagrams (Mermaid.js, PlantUML, or draw.io) +- [ ] [P3] [E:M] Create example code snippets +- [ ] [P3] [E:M] Expand requirements documentation +- [ ] [P3] [E:M] Add cross-references to other module docs + +## Code Quality Tasks + +**Reference:** [../QUALITY_PLAYBOOK.md](../QUALITY_PLAYBOOK.md) + +- [ ] [P2] [E:M] Run Checkstyle scan and document violations +- [ ] [P2] [E:M] Run SpotBugs scan and document issues +- [ ] [P2] [E:M] Identify any code review follow-ups from CODE_REVIEW_STATUS.md + +## Notes + +[Add any module-specific notes, blockers, or context here] + +## Completion Checklist + +Before marking this repository's contribution to ARCH_TODO as complete: + +- [ ] [P1] [E:S] All "Module Information" sections filled out +- [ ] [P1] [E:S] Existing documentation audited +- [ ] [P1] [E:S] Requirements identified for ARCH_TODO Stage 1.75 +- [ ] [P1] [E:S] Decisions identified for ARCH_TODO Stage 1.85 +- [ ] [P1] [E:S] Glossary terms identified for ARCH_TODO Stage 1.5 +- [ ] [P1] [E:S] Documentation gaps documented +- [ ] [P1] [E:S] Improvement tasks prioritized +- [ ] [P1] [E:S] Information contributed to relevant ARCH_TODO stages + +--- + +**When complete, update:** [../ARCH_TODO.md](../ARCH_TODO.md) Stage 3 tracking matrix diff --git a/effective-pom.xml b/effective-pom.xml new file mode 100644 index 0000000..b82b722 --- /dev/null +++ b/effective-pom.xml @@ -0,0 +1,1352 @@ + + + + + + + + + + + + + + + 4.0.0 + + net.openhft + java-parent-pom + 1.27ea2-SNAPSHOT + + + net.openhft + compiler + 2.27ea4-SNAPSHOT + bundle + OpenHFT/Java-Runtime-Compiler + Java Runtime Compiler library. + https://chronicle.software/java-parent-pom/compiler + + Chronicle Software Ltd + https://chronicle.software/ + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + + + + + Peter Lawrey + peter.lawrey@chronicle.software + + + Rob Austin + rob.austin@chronicle.software + + + Roger Simmons + roger.simmons@chronicle.software + + + Jerry Shea + jerry.shea@chronicle.software + + + Ryan Andrews + ryan.andrews@chronicle.software + + + Tom Dellmann + tom.dellmann@chronicle.software + + + + scm:git:git@github.com:OpenHFT/Java-Runtime-Compiler.git + scm:git:git@github.com:OpenHFT/Java-Runtime-Compiler.git + ea + scm:git:git@github.com:OpenHFT/Java-Runtime-Compiler.git + + + + sonatype-nexus-staging + https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/ + + + sonatype-nexus-snapshots + https://central.sonatype.com/repository/maven-snapshots/ + + + + + net/openhft/quality/checkstyle27/chronicle-baseline-checkstyle.xml + false + warning + 0.3 + 0.5 + + chronicle.software + false + Apache-2.0 + 2013-2025 + UTF-8 + https://sonarcloud.io + openhft + + + + + + io.opentelemetry + opentelemetry-api + 1.12.0 + + + io.opentelemetry + opentelemetry-sdk + 1.12.0 + + + io.opentelemetry + opentelemetry-exporter-otlp + 1.12.0 + + + org.skyscreamer + jsonassert + 1.5.1 + + + com.samskivert + samskivert + 1.9 + + + org.yaml + snakeyaml + 2.0 + + + com.thoughtworks.xstream + xstream + 1.4.20 + + + org.mongodb + bson + 4.10.2 + + + org.mongodb + mongodb-driver + 3.12.14 + + + org.mongodb + mongo-java-driver + 3.12.14 + + + io.undertow + undertow-servlet + 2.2.25.Final + + + io.undertow + undertow-websockets-jsr + 2.2.25.Final + + + io.undertow + undertow-core + 2.2.25.Final + + + org.mongodb + mongodb-driver-core + 4.10.2 + + + com.koloboke + koloboke-api-jdk8 + 1.0.0 + + + com.koloboke + koloboke-compile + 0.5.1 + + + com.koloboke + koloboke-impl-common-jdk8 + 1.0.0 + + + org.mongodb + mongodb-driver-sync + 4.10.2 + + + org.eclipse.jetty.aggregate + jetty-all + 9.4.46.v20220331 + pom + + + org.junit.jupiter + junit-jupiter + 5.10.0 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.10.0 + test + + + org.junit.jupiter + junit-jupiter-api + 5.10.0 + test + + + org.junit.vintage + junit-vintage-engine + 5.10.0 + test + + + org.junit.jupiter + junit-jupiter-params + 5.10.0 + test + + + org.junit.platform + junit-platform-engine + 1.10.0 + test + + + org.junit.platform + junit-platform-commons + 1.10.0 + test + + + org.junit.platform + junit-platform-launcher + 1.10.0 + test + + + org.junit.jupiter + junit-jupiter-migrationsupport + 1.10.0 + test + + + com.squareup.okhttp3 + mockwebserver + 4.9.3 + + + org.xerial.snappy + snappy-java + 1.1.10.3 + + + org.apache.logging.log4j + log4j-core + 2.17.2 + + + org.apache.logging.log4j + log4j-api + 2.17.2 + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.17.2 + + + org.apache.logging.log4j + log4j-jul + 2.17.2 + + + org.apache.servicemix.bundles + org.apache.servicemix.bundles.quickfix + 1.6.4_1 + + + log4j + log4j + 1.2.17 + + + org.openjdk.jmh + jmh-core + 1.36 + + + org.openjdk.jmh + jmh-core-benchmarks + 1.36 + + + org.openjdk.jmh + jmh-generator-annprocess + 1.36 + test + + + org.hamcrest + hamcrest-all + 1.3 + + + javax.inject + javax.inject + 1 + + + org.slf4j + slf4j-api + 1.7.36 + + + org.slf4j + slf4j-simple + 1.7.36 + + + org.slf4j + slf4j-nop + 1.7.36 + + + junit + junit + 4.13.2 + + + org.osgi + org.osgi.core + 6.0.0 + + + org.osgi + org.osgi.compendium + 5.0.0 + + + org.ops4j.pax.exam + pax-exam-container-native + 4.13.5 + + + org.ops4j.pax.exam + pax-exam-junit4 + 4.13.5 + + + org.ops4j.pax.exam + pax-exam-link-mvn + 4.13.5 + + + org.ops4j.pax.url + pax-url-aether + 2.6.12 + + + org.ops4j.pax.url + pax-url-reference + 2.6.12 + + + org.apache.felix + org.apache.felix.framework + 7.0.5 + + + net.sf.trove4j + core + 3.1.0 + + + ch.qos.logback + logback-core + 1.2.12 + + + ch.qos.logback + logback-classic + 1.2.12 + + + net.java.dev.jna + jna + 5.5.0 + + + net.java.dev.jna + jna-platform + 5.5.0 + + + org.easymock + easymock + 5.1.0 + + + org.jetbrains + annotations + 24.0.1 + provided + + + com.google.guava + guava-testlib + 33.1.0-jre + test + + + org.apache.commons + commons-lang3 + 3.12.0 + + + commons-cli + commons-cli + 1.5.0 + + + commons-logging + commons-logging + 1.3.5 + + + org.mockito + mockito-core + 4.11.0 + + + org.mockito + mockito-junit-jupiter + 4.11.0 + + + org.powermock + powermock-module-junit4 + 2.0.9 + + + org.powermock + powermock-api-mockito + 1.7.4 + + + org.codehaus.jettison + jettison + 1.5.4 + + + io.github.classgraph + classgraph + 4.8.161 + + + com.squareup + javapoet + 1.13.0 + + + org.eclipse.jetty.websocket + websocket-api + 9.4.46.v20220331 + + + org.eclipse.jetty.websocket + websocket-server + 9.4.46.v20220331 + + + org.eclipse.jetty.websocket + websocket-client + 9.4.46.v20220331 + + + org.jboss.xnio + xnio-nio + 3.8.9.Final + + + net.sf.proguard + proguard-base + 6.2.2 + + + org.glassfish.grizzly + grizzly-framework + 2.3.31 + + + org.apache.mina + mina-core + 2.2.2 + + + io.netty + netty-all + 5.0.0.Alpha2 + + + org.hsqldb + hsqldb + 2.7.1 + + + org.hsqldb + hsqldb + 2.7.1 + jdk8 + + + jakarta.xml.bind + jakarta.xml.bind-api + 2.3.3 + + + com.fasterxml.jackson.module + jackson-module-jsonSchema + 2.14.2 + + + io.prometheus + simpleclient + 0.16.0 + + + io.prometheus + simpleclient_hotspot + 0.16.0 + + + io.prometheus + simpleclient_httpserver + 0.16.0 + + + com.github.jnr + jnr-constants + 0.10.4 + + + com.github.jnr + jnr-ffi + 2.2.15 + + + org.ow2.asm + asm-analysis + + + org.ow2.asm + asm-commons + + + org.ow2.asm + asm-tree + + + org.ow2.asm + asm-util + + + + + + + + org.slf4j + slf4j-api + 1.7.36 + compile + + + org.jetbrains + annotations + 24.0.1 + provided + + + org.easymock + easymock + 5.1.0 + test + + + junit + junit + 4.13.2 + test + + + org.slf4j + slf4j-simple + 1.7.36 + test + + + + + + false + never + + + true + always + + Snapshot Repository + Snapshot Repository + https://central.sonatype.com/repository/maven-snapshots/ + + + + false + + central + Central Repository + https://repo.maven.apache.org/maven2 + + + + + + false + + central + Central Repository + https://repo.maven.apache.org/maven2 + + + + /home/peter/Second/Java-Runtime-Compiler/src/main/java + /home/peter/Second/Java-Runtime-Compiler/src/main/scripts + /home/peter/Second/Java-Runtime-Compiler/src/test/java + /home/peter/Second/Java-Runtime-Compiler/target/classes + /home/peter/Second/Java-Runtime-Compiler/target/test-classes + + + /home/peter/Second/Java-Runtime-Compiler/src/main/resources + + + + + /home/peter/Second/Java-Runtime-Compiler/src/test/resources + + + /home/peter/Second/Java-Runtime-Compiler/target + compiler-2.27ea4-SNAPSHOT + + + + maven-antrun-plugin + 3.1.0 + + + maven-gpg-plugin + 3.1.0 + + + maven-enforcer-plugin + 3.3.0 + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.13 + + + maven-scm-publish-plugin + 3.1.0 + + + maven-resources-plugin + 3.3.1 + + + org.apache.felix + maven-bundle-plugin + 5.1.9 + + + org.apache.servicemix.tooling + depends-maven-plugin + 1.5.0 + + + com.google.code.maven-replacer-plugin + replacer + 1.5.3 + + + maven-assembly-plugin + 3.6.0 + + + maven-dependency-plugin + 3.6.0 + + + maven-install-plugin + 3.1.1 + + + maven-site-plugin + 3.12.1 + + + maven-clean-plugin + 3.2.0 + + + maven-compiler-plugin + 3.14.0 + + + maven-javadoc-plugin + 3.5.0 + + + maven-source-plugin + 3.3.0 + + + maven-deploy-plugin + 3.1.1 + + + maven-surefire-plugin + 3.1.2 + + + maven-shade-plugin + 3.5.0 + + + maven-jar-plugin + 3.3.0 + + + maven-release-plugin + 3.0.1 + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + org.sonarsource.scanner.maven + sonar-maven-plugin + 3.9.1.2184 + + + org.jacoco + jacoco-maven-plugin + 0.8.14 + + + com.github.ferstl + depgraph-maven-plugin + 4.0.2 + + compile + + + + net.openhft + binary-compatibility-enforcer-plugin + 1.0.13 + + + + + + maven-release-plugin + 3.0.1 + + true + forked-path + false + + + + maven-enforcer-plugin + 3.3.0 + + + enforce-maven + + enforce + + + + + 3.5.4 + + + + + + enforce-no-snapshots + + enforce + + + + + No Snapshots Allowed! + true + + + true + + + + + + com.mycila + license-maven-plugin + 4.6 + + + license-check + + check + + + false + UTF-8 + true + + 2013-2025 + chronicle.software + Apache-2.0 + + + SLASHSTAR_STYLE + SCRIPT_STYLE + + + + Copyright 2013-2025 chronicle.software; SPDX-License-Identifier: Apache-2.0 + + **/*.java + **/*.sh + + + **/target/** + **/generated-sources/** + **/build/generated/** + **/src/test/resources/** + **/src/main/resources/** + + true + + + + + + + false + UTF-8 + true + + 2013-2025 + chronicle.software + Apache-2.0 + + + SLASHSTAR_STYLE + SCRIPT_STYLE + + + + Copyright 2013-2025 chronicle.software; SPDX-License-Identifier: Apache-2.0 + + **/*.java + **/*.sh + + + **/target/** + **/generated-sources/** + **/build/generated/** + **/src/test/resources/** + **/src/main/resources/** + + true + + + + + + maven-surefire-plugin + 3.1.2 + + + default-test + test + + test + + + -Djvm.coverage=true + + /home/peter/Second/Java-Runtime-Compiler/target + + true + + + + + -Djvm.coverage=true + + /home/peter/Second/Java-Runtime-Compiler/target + + true + + + + maven-scm-publish-plugin + 3.1.0 + + /home/peter/Second/Java-Runtime-Compiler/target/scmpublish/javadoc + Publishing javadoc for compiler:2.27ea4-SNAPSHOT + /home/peter/Second/Java-Runtime-Compiler/target/site + true + scm:git:git@github.com:OpenHFT/compiler + gh-pages + + + + maven-source-plugin + 3.3.0 + + + attach-sources + + jar + + + + + + maven-compiler-plugin + 3.14.0 + + + default-compile + compile + + compile + + + false + + -Xlint:all,-options,-processing + -parameters + + 1.8 + 1.8 + UTF-8 + true + true + none + + + + default-testCompile + test-compile + + testCompile + + + false + + -Xlint:all,-options,-processing + -parameters + + 1.8 + 1.8 + UTF-8 + true + true + none + + + + + false + + -Xlint:all,-options,-processing + -parameters + + 1.8 + 1.8 + UTF-8 + true + true + none + + + + maven-javadoc-plugin + 3.5.0 + + + attach-javadocs + + jar + + + false + 8 + ${javadoc.opts} + true + *.internal:*.internal.*;*.impl;*.impl.* + all,-missing + + + + + false + 8 + ${javadoc.opts} + true + *.internal:*.internal.*;*.impl;*.impl.* + all,-missing + + + + org.apache.servicemix.tooling + depends-maven-plugin + 1.5.0 + + + generate-depends-file + + generate-depends-file + + + + + + org.apache.felix + maven-bundle-plugin + 5.1.9 + true + + + default-bundle + package + + bundle + + + + net.openhft.compiler + net.openhft.compiler + OpenHFT :: compiler + 2.27ea4-SNAPSHOT + net.openhft.compiler.*;-noimport:=true + + + + + default-install + install + + install + + + + net.openhft.compiler + net.openhft.compiler + OpenHFT :: compiler + 2.27ea4-SNAPSHOT + net.openhft.compiler.*;-noimport:=true + + + + + default-deploy + deploy + + deploy + + + + net.openhft.compiler + net.openhft.compiler + OpenHFT :: compiler + 2.27ea4-SNAPSHOT + net.openhft.compiler.*;-noimport:=true + + + + + + manifest + + + + net.openhft.compiler + net.openhft.compiler + OpenHFT :: compiler + 2.27ea4-SNAPSHOT + net.openhft.compiler.*;-noimport:=true + + + + + + + net.openhft.compiler + net.openhft.compiler + OpenHFT :: compiler + 2.27ea4-SNAPSHOT + net.openhft.compiler.*;-noimport:=true + + + + + maven-checkstyle-plugin + 3.6.0 + + net/openhft/quality/checkstyle27/chronicle-baseline-checkstyle.xml + true + true + true + warning + + + + maven-clean-plugin + 3.2.0 + + + default-clean + clean + + clean + + + + + + maven-resources-plugin + 3.3.1 + + + default-testResources + process-test-resources + + testResources + + + + default-resources + process-resources + + resources + + + + + + maven-install-plugin + 3.1.1 + + + default-install + install + + install + + + + + + maven-deploy-plugin + 3.1.1 + + + default-deploy + deploy + + deploy + + + + + + maven-site-plugin + 3.12.1 + + + default-site + site + + site + + + /home/peter/Second/Java-Runtime-Compiler/target/site + + + org.apache.maven.plugins + maven-project-info-reports-plugin + + + + + + default-deploy + site-deploy + + deploy + + + /home/peter/Second/Java-Runtime-Compiler/target/site + + + org.apache.maven.plugins + maven-project-info-reports-plugin + + + + + + + /home/peter/Second/Java-Runtime-Compiler/target/site + + + org.apache.maven.plugins + maven-project-info-reports-plugin + + + + + + + + /home/peter/Second/Java-Runtime-Compiler/target/site + + + + prejava17 + + [8,17] + + + + + org.codehaus.mojo + exec-maven-plugin + + + compiler-test + integration-test + + java + + + + + test + net.openhft.compiler.CompilerTest + + + + + + + quality + + [11,) + + + + + maven-checkstyle-plugin + 3.3.0 + + + validate + validate + + check + + + + + + com.puppycrawl.tools + checkstyle + 9.3 + + + net.openhft + chronicle-quality-rules + 1.27.0-SNAPSHOT + + + + net/openhft/quality/checkstyle27/chronicle-baseline-checkstyle.xml + true + true + true + warning + + + + com.github.spotbugs + spotbugs-maven-plugin + 4.9.8.1 + + + spotbugs-main + process-classes + + check + + + + + + net.openhft + chronicle-quality-rules + 1.27.0-SNAPSHOT + + + + Max + Low + true + true + net/openhft/quality/spotbugs27/chronicle-spotbugs-include.xml + net/openhft/quality/spotbugs27/chronicle-spotbugs-exclude.xml + + + + + + + diff --git a/src/main/java/net/openhft/compiler/package-info.java b/src/main/java/net/openhft/compiler/package-info.java new file mode 100644 index 0000000..a8aefaf --- /dev/null +++ b/src/main/java/net/openhft/compiler/package-info.java @@ -0,0 +1,8 @@ +/** + * Runtime Java compilation utilities based on the standard {@code javax.tools} API. + * + *

Classes here compile source strings and byte arrays on the fly, cache + * generated classes, and provide convenience wrappers for loading the results at + * runtime. + */ +package net.openhft.compiler; From 01ac48c45a9bd6161d0c2b5f84b3e4da4db62092 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Mon, 24 Nov 2025 11:57:37 +0000 Subject: [PATCH 11/13] Remove JDK activation from quality profile in pom.xml --- pom.xml | 55 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 58d0e12..236f9df 100644 --- a/pom.xml +++ b/pom.xml @@ -185,29 +185,72 @@ + - module-quality - - [11,) - + quality + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.3.0 + + + validate + validate + + check + + + + + ${checkstyle.config.location} + true + true + true + ${checkstyle.violationSeverity} + + + + com.puppycrawl.tools + checkstyle + 9.3 + + + net.openhft + chronicle-quality-rules + 1.27.0-SNAPSHOT + + + com.github.spotbugs spotbugs-maven-plugin + 4.9.8.1 Max Low true true + + net/openhft/quality/spotbugs27/chronicle-spotbugs-include.xml + net/openhft/quality/spotbugs27/chronicle-spotbugs-exclude.xml + + + net.openhft + chronicle-quality-rules + 1.27.0-SNAPSHOT + + spotbugs-main - process-classes + + process-test-classes - spotbugs + check From 6e69286a3f2f78ec1e850777d2159a672ea71f02 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Mon, 24 Nov 2025 12:08:32 +0000 Subject: [PATCH 12/13] Add copyright notice and SPDX license identifier to package-info.java --- src/main/java/net/openhft/compiler/package-info.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/net/openhft/compiler/package-info.java b/src/main/java/net/openhft/compiler/package-info.java index a8aefaf..7e6d821 100644 --- a/src/main/java/net/openhft/compiler/package-info.java +++ b/src/main/java/net/openhft/compiler/package-info.java @@ -1,3 +1,6 @@ +/* + * Copyright 2013-2025 chronicle.software; SPDX-License-Identifier: Apache-2.0 + */ /** * Runtime Java compilation utilities based on the standard {@code javax.tools} API. * From bdb9f418e878f3dc4411ae41b0ce9efd7bf3eefd Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Fri, 28 Nov 2025 11:00:16 +0000 Subject: [PATCH 13/13] Only run checkstyle with quality profile --- pom.xml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/pom.xml b/pom.xml index 236f9df..c94490b 100644 --- a/pom.xml +++ b/pom.xml @@ -140,18 +140,6 @@ - - - org.apache.maven.plugins - maven-checkstyle-plugin - - ${checkstyle.config.location} - true - true - true - ${checkstyle.violationSeverity} - -