Skip to content

Commit a19a5d2

Browse files
UnbreakableMJAntigravity (Gemini 3.5 Flash)
andcommitted
feat(skills): add spacecraft-java-guidelines
Introduce a new language-guidelines skill for Java systems programming. Defines rules and checklists for Project Loom Virtual Threads (banning virtual thread pooling), preventing carrier thread pinning (replacing synchronized blocks with ReentrantLock), structured concurrency workflows via StructuredTaskScope, memory/resource safety via try-with-resources, Generational ZGC runtime flags for low-latency, and sequenced collections. Re-orders Kotlin guidelines in README.md to fix sorting. Co-Authored-By: Antigravity (Gemini 3.5 Flash) <noreply@google.com>
1 parent af6d709 commit a19a5d2

5 files changed

Lines changed: 353 additions & 1 deletion

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@ the rules re-attached to every prompt.
4747
| [`spacecraft-document-format`](spacecraft-document-format/) | Texinfo-first document authoring: `.texi` is canonical for prose (one source → Info/text, HTML, PDF, and GFM; Standard §8), ODF (`.odt`/`.ods`/`.odp`) is secondary for prose and primary for spreadsheets/presentations, MS Office (`.docx`/`.xlsx`/`.pptx`) is the last-resort fallback; GFM Markdown companion paired with every binary deliverable; PDF always an export; CC-BY-SA-4.0 document license; Void Navy + Standard §11 palette. |
4848
| [`spacecraft-elixir-guidelines`](spacecraft-elixir-guidelines/) | Fault-tolerant concurrent Elixir/OTP guidance — supervision trees, `GenServer`/`Task.async_stream`, "let it crash" resilience, share-nothing message passing, pattern matching & `with` flow, ExUnit/StreamData testing, and `mix format`/Credo/Dialyzer gates. |
4949
| [`spacecraft-erlang-guidelines`](spacecraft-erlang-guidelines/) | Fault-tolerant concurrent Erlang/OTP guidance — `gen_server`/`gen_statem`/`supervisor` behaviours, restart strategies, links & monitors, "let it crash", ETS/Mnesia state, `-spec` + Dialyzer, and the rebar3 (eunit/Common Test/xref/dialyzer) toolchain. |
50-
| [`spacecraft-kotlin-guidelines`](spacecraft-kotlin-guidelines/) | Type-safe highly-concurrent Kotlin guidance — structured concurrency, `supervisorScope` failure isolation, injected dispatchers (`IO`/`Default`/`Main`), null safety (avoiding `!!`), Exposed ORM transaction boundaries, and functional `Either` error mappers. |
5150
| [`spacecraft-gleam-guidelines`](spacecraft-gleam-guidelines/) | Type-safe fault-tolerant Gleam-on-the-BEAM guidance — gleam_otp 1.x typed actors and static/factory supervision, `Subject` message passing, `Result`/`use` error flow, exhaustive `case`, `@external` FFI discipline, gleeunit/qcheck/birdie testing, and the `gleam format --check` / `build --warnings-as-errors` gates. |
5251
| [`spacecraft-golang-guidelines`](spacecraft-golang-guidelines/) | High-performance concurrent Go guidance — goroutines, channels, errgroup, context cancellation, atomics, `sync.Pool`, pprof / race-detector workflow, and memory-safe parallelism patterns. |
52+
| [`spacecraft-java-guidelines`](spacecraft-java-guidelines/) | Type-safe concurrent Java guidance — Virtual Threads (Project Loom), structured concurrency (`StructuredTaskScope`), avoiding thread pinning, garbage collection tuning (Generational ZGC), try-with-resources resource safety, and immutable records. |
53+
| [`spacecraft-kotlin-guidelines`](spacecraft-kotlin-guidelines/) | Type-safe highly-concurrent Kotlin guidance — structured concurrency, `supervisorScope` failure isolation, injected dispatchers (`IO`/`Default`/`Main`), null safety (avoiding `!!`), Exposed ORM transaction boundaries, and functional `Either` error mappers. |
5354
| [`spacecraft-markdown-document`](spacecraft-markdown-document/) | Produces well-formed GFM documents conforming to the GitHub Flavored Markdown spec and Spacecraft Software house style. Slash-command only: `/spacecraft-markdown-document`. |
5455
| [`spacecraft-missing-pkg`](spacecraft-missing-pkg/) | Handles missing-package situations in the Spacecraft Software workflow. |
5556
| [`spacecraft-nim-guidelines`](spacecraft-nim-guidelines/) | Type-safe highly-concurrent Nim guidance (targeting Nim 2.0+) — ARC/ORC deterministic memory management, move semantics (`sink`/`lent`), structured parallelism via `Malebolgia`, asynchronous networking with `Chronos`, safe FFI custom destructors (`=destroy`), and warnings-as-errors compiler configuration. |

spacecraft-java-guidelines.skill

6.54 KB
Binary file not shown.

spacecraft-java-guidelines.zip

6.74 KB
Binary file not shown.
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
name: spacecraft-java-guidelines
3+
description: Use for writing memory-safe highly-concurrent Java code following Spacecraft Software standards. Triggers on any request involving Java, JVM, JDK, OpenJDK, virtual threads (Project Loom), thread pinning, Structured Concurrency (StructuredTaskScope), Scoped Values, Sequenced Collections, record classes, try-with-resources, Generational ZGC (-XX:+UseZGC -XX:+ZGenerational), G1GC, thread safety, or concurrency synchronization. Trigger even when implicit, e.g. "write a concurrent Java task scheduler", "debug virtual thread pinning", "avoid Java memory leaks", or "configure G1GC tuning". Do NOT trigger for Kotlin, Clojure, Scala, or Android unless interoperability is explicitly requested. By Mohamed Hammad and Spacecraft Software.
4+
license: GPL-3.0-or-later
5+
maintainer: Mohamed Hammad <Mohamed.Hammad@SpacecraftSoftware.org>
6+
website: https://Construct.SpacecraftSoftware.org/
7+
---
8+
9+
# Spacecraft Java Guidelines
10+
11+
**Maintainer:** Mohamed Hammad | **Contact:** [Mohamed.Hammad@SpacecraftSoftware.org](mailto:Mohamed.Hammad@SpacecraftSoftware.org)
12+
**Copyright:** (C) 2026 Mohamed Hammad & Spacecraft Software | **License:** GPL-3.0-or-later
13+
**Website:** [https://Construct.SpacecraftSoftware.org/](https://Construct.SpacecraftSoftware.org/)
14+
15+
**You are an expert Java systems engineer at Spacecraft Software specializing in memory-safe, highly-concurrent, and low-latency JVM systems.** Always follow these rules when writing or reviewing Java code. Never deviate. Instructions are explicit, checklist-driven, and self-contained.
16+
17+
## Core Philosophy
18+
- **Stability and Safety first (Standard §3 Priority 1).** Java is memory-safe but prone to reference-type leaks, null pointer exceptions, and concurrent synchronization deadlocks. Manage resource lifetimes explicitly, ensure robust null safety boundaries using `Optional` and static annotations, and enforce strict concurrent safety.
19+
- **Then Performance (Priority 2).** Do not introduce excessive GC pauses or boxing overheads. Tune the garbage collector for latency or throughput depending on workloads.
20+
- **Project Loom Concurrency.** Prefer lightweight Virtual Threads (Java 21+) for high-concurrency task processing. Never pool virtual threads. Manage concurrent subtask hierarchies using Structured Concurrency.
21+
- **Immutability by Default.** Use `record` classes to represent data carriers. Prefer final declarations to prevent unintended mutation.
22+
23+
## Memory Safety & Resource Hygiene
24+
- **Null Safety:** Public APIs must not return `null`. Use `Optional<T>` to indicate optional values. Annotate parameters and return values with `@NonNull` or `@Nullable` to support compile-time static analysis check-gates.
25+
- **Resource Management:** Every resource implementing `AutoCloseable` (e.g. databases, sockets, input/output streams) must be managed using `try-with-resources` to guarantee deterministic cleanup.
26+
- **Memory Leak Prevention:** Banish memory leaks by avoiding static references to collections (caches, listener sets) without eviction strategies. Use `WeakReference` or eviction libraries (e.g., Caffeine) for long-lived caches.
27+
- **Primitive Boxing Avoidance:** Banish primitive boxing overhead in performance-critical calculation paths. Prefer primitive streams (`IntStream`, `LongStream`, `DoubleStream`) and primitive collections.
28+
29+
## Concurrency vs. Performance Tradeoffs
30+
- **When Concurrency Helps (Do Thread Safety):**
31+
- **High-throughput I/O:** Using Virtual Threads to execute I/O-bound tasks concurrently without blocking platform threads.
32+
- **Thread-Per-Task Execution:** Creating short-lived Virtual Threads per task instead of pooling them.
33+
- **Structured Subtasks:** Utilizing `StructuredTaskScope` (JEP 462+) to coordinate subtasks, guaranteeing that when a task is cancelled, all sibling subtasks are cleanly aborted.
34+
- **Scoped Data Sharing:** Using `ScopedValue` (JEP 464+) instead of `ThreadLocal` for safe, immutable data propagation down execution scopes.
35+
- **When Concurrency Hurts (Do NOT Block / Pin):**
36+
- **Virtual Thread Pinning:** Do NOT execute blocking calls (I/O, locks) inside a `synchronized` block or method. This pins the virtual thread to the carrier platform thread, causing starvation. Replace `synchronized` with `ReentrantLock` in I/O paths.
37+
- **Virtual Thread Pooling:** Never pool virtual threads. Thread pools exist to limit expensive platform resources. Virtual threads are cheap and should be created on-demand.
38+
- **Shared Writable State:** Mutating collections (e.g. `ArrayList`, `HashMap`) concurrently without synchronized access. Use `ConcurrentHashMap` or explicit locks.
39+
40+
## Mandatory Abstraction Choice
41+
Always choose the correct concurrent and structural abstraction:
42+
- **I/O-Bound Task Concurrency:** Java 21+ Virtual Threads via `Thread.ofVirtual().start()` or `Executors.newVirtualThreadPerTaskExecutor()`.
43+
- **Compute-Bound Task Concurrency:** ForkJoinPool or traditional fixed-size ExecutorService threads scaled to CPU core count.
44+
- **Multi-mutex locking or Virtual Thread paths:** `java.util.concurrent.locks.ReentrantLock`.
45+
- **Dynamic Data Sharing:** Scoped Values (`ScopedValue`) rather than `ThreadLocal`.
46+
- **Data Carriers:** `record` classes.
47+
48+
## Required Techniques
49+
1. **Virtual Thread Executors:** Wrap I/O task flows in `try (var executor = Executors.newVirtualThreadPerTaskExecutor())`.
50+
2. **ReentrantLock over synchronized:** Replace `synchronized` declarations with `ReentrantLock` in class methods that execute blocking network or disk database queries.
51+
3. **StructuredTaskScope for Subtasks:** Coalesce multiple parallel API fetches inside a `StructuredTaskScope.ShutdownOnFailure` to capture all errors.
52+
4. **Try-With-Resources:** Every file, channel, or socket must be nested in a `try (...) { ... }` block.
53+
5. **Generational ZGC Configuration:** Launch low-latency services using JVM arguments: `-XX:+UseZGC -XX:+ZGenerational`.
54+
55+
## Build, Tooling & CI (Non-Negotiable)
56+
- **Toolchain floor:** JDK 21+, Gradle 8.0+ or Maven 3.8+.
57+
- **Warnings-as-Errors:** Configure compiler flags to fail builds on warnings: `-Xlint:all -Werror`.
58+
- **Formatting Check:** Enforce automated style formatting checks (e.g., Spotless) in CI pipelines.
59+
- **Testing:** Verify all features using JUnit 5.
60+
61+
## Anti-Patterns (Never Do These)
62+
- Pooling virtual threads (e.g., using virtual threads in a bounded `ThreadPoolExecutor`).
63+
- Calling I/O or locking inside `synchronized` blocks when running under virtual threads (thread pinning).
64+
- Returning `null` from public API methods (use `Optional` or annotation constraints).
65+
- Leaving resource streams open without `try-with-resources`.
66+
- Storing unbounded items in static collections without eviction policies.
67+
- Using `ThreadLocal` for passing data down a call tree (use `ScopedValue`).
68+
- Throwing generic `RuntimeException` or swallowing exceptions without logging.
69+
70+
## Pre-Commit Checklist (Verify Every Time)
71+
- [ ] No raw `synchronized` blocks perform I/O operations (use `ReentrantLock`)
72+
- [ ] Virtual threads are spawned per-task and are not pooled
73+
- [ ] All resources implementing `AutoCloseable` are wrapped in `try-with-resources`
74+
- [ ] Public API signatures return `Optional` instead of `null` for missing values
75+
- [ ] Structured concurrency tasks are managed via `StructuredTaskScope`
76+
- [ ] Low-latency JVM services configure `-XX:+UseZGC -XX:+ZGenerational`
77+
- [ ] Code compiles clean under `-Xlint:all -Werror` compiler parameters
78+
- [ ] JUnit 5 tests run and pass successfully
79+
- [ ] Spotless formatting check passes cleanly
80+
81+
## References & Further Reading
82+
- Load `references/Spacecraft_Java_Guidelines.md` for full code skeletons (Virtual thread worker, Structured Concurrency ShutdownOnFailure scope, try-with-resources client, and JUnit 5 suite).
83+
- *Further reading* (consulted for background only): JEP 444 (Virtual Threads), JEP 462 (Structured Concurrency), JEP 439 (Generational ZGC), Java Core Guidelines.
Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
# Spacecraft Java Guidelines — Full Reference
2+
3+
**Version:** 1.0
4+
**Date:** 2026-07-13
5+
**Author:** Mohamed Hammad & Spacecraft Software
6+
**Compatibility:** JDK 21+, OpenJDK 21+, Generational ZGC
7+
8+
This document expands on the `SKILL.md` for Java systems programming. It provides complete, compile-checked configurations and skeletons for Virtual Threads, Structured Concurrency, resource management, and unit testing.
9+
10+
---
11+
12+
## 1. Virtual Threads (Project Loom) Executor Flow
13+
14+
Virtual threads are lightweight, user-mode threads scheduled by the JVM on carrier platform threads. Never pool virtual threads. Create them on-demand per task.
15+
16+
```java
17+
package org.spacecraftsoftware.telemetry;
18+
19+
import java.util.List;
20+
import java.util.concurrent.Callable;
21+
import java.util.concurrent.ExecutionException;
22+
import java.util.concurrent.Executors;
23+
import java.util.concurrent.Future;
24+
25+
public class VirtualThreadProcessor {
26+
27+
public record TelemetryTask(String sensorId) implements Callable<Double> {
28+
@Override
29+
public Double call() throws Exception {
30+
// Simulate blocking I/O network poll
31+
Thread.sleep(50);
32+
return Math.random() * 100.0;
33+
}
34+
}
35+
36+
public List<Double> fetchAllTelemetry(List<String> sensorIds) throws InterruptedException {
37+
// CRITICAL: Banish thread pools for virtual threads. Spawn on-demand.
38+
// Use try-with-resources to automatically close the executor (which awaits task completion).
39+
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
40+
List<TelemetryTask> tasks = sensorIds.stream()
41+
.map(TelemetryTask::new)
42+
.toList();
43+
44+
List<Future<Double>> futures = executor.invokeAll(tasks);
45+
46+
return futures.stream()
47+
.map(f -> {
48+
try {
49+
return f.get();
50+
} catch (InterruptedException | ExecutionException e) {
51+
Thread.currentThread().interrupt();
52+
throw new RuntimeException("Telemetry fetch failed", e);
53+
}
54+
})
55+
.toList();
56+
}
57+
}
58+
}
59+
```
60+
61+
---
62+
63+
## 2. Preventing Virtual Thread Pinning with ReentrantLock
64+
65+
Avoid using `synchronized` blocks or methods when executing blocking I/O inside virtual threads. If a virtual thread blocks inside `synchronized`, it pins its carrier platform thread, causing carrier thread starvation. Replace `synchronized` with `ReentrantLock`.
66+
67+
```java
68+
package org.spacecraftsoftware.telemetry;
69+
70+
import java.util.ArrayList;
71+
import java.util.List;
72+
import java.util.concurrent.locks.ReentrantLock;
73+
74+
public class PinFreeTelemetryLogger {
75+
76+
private final ReentrantLock lock = new ReentrantLock();
77+
private final List<String> logs = new ArrayList<>();
78+
79+
public void logEvent(String event) {
80+
// CRITICAL: Replace synchronized(this) { ... } with explicit ReentrantLock
81+
// to prevent pinning the carrier thread during downstream blocking calls.
82+
lock.lock();
83+
try {
84+
logs.add(event);
85+
// Simulate blocking write (disk write / network flush)
86+
writeToDisk(event);
87+
} finally {
88+
lock.unlock(); // Always release inside finally block
89+
}
90+
}
91+
92+
private void writeToDisk(String data) {
93+
try {
94+
// Simulate blocking disk I/O
95+
Thread.sleep(10);
96+
} catch (InterruptedException e) {
97+
Thread.currentThread().interrupt();
98+
}
99+
}
100+
101+
public List<String> getLogs() {
102+
lock.lock();
103+
try {
104+
return List.copyOf(logs);
105+
} finally {
106+
lock.unlock();
107+
}
108+
}
109+
}
110+
```
111+
112+
---
113+
114+
## 3. Structured Concurrency (JEP 462+)
115+
116+
Structured Concurrency treats groups of concurrent tasks as a single unit of work, improving reliability and cancellation tracking.
117+
118+
```java
119+
package org.spacecraftsoftware.telemetry;
120+
121+
import java.util.concurrent.StructuredTaskScope;
122+
import java.util.concurrent.StructuredTaskScope.Subtask;
123+
import java.time.Instant;
124+
125+
public class ResilientTaskScheduler {
126+
127+
public record ServiceResponse(String data, Instant timestamp) {}
128+
129+
public ServiceResponse queryResilientData() throws Exception {
130+
// Use StructuredTaskScope to coordinate subtasks. ShutdownOnFailure shuts down
131+
// all subtasks immediately if any single subtask fails (fail-fast behavior).
132+
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
133+
134+
// Fork subtask queries
135+
Subtask<String> dbSubtask = scope.fork(() -> queryDatabase());
136+
Subtask<Instant> timeSubtask = scope.fork(() -> fetchNetworkTime());
137+
138+
scope.join(); // Join both subtasks
139+
scope.throwIfFailed(); // Propagate exceptions if any subtask failed
140+
141+
// Safe retrieval of results
142+
return new ServiceResponse(dbSubtask.get(), timeSubtask.get());
143+
}
144+
}
145+
146+
private String queryDatabase() throws Exception {
147+
Thread.sleep(30);
148+
return "Spacecraft Coordinates Active";
149+
}
150+
151+
private Instant fetchNetworkTime() throws Exception {
152+
Thread.sleep(20);
153+
return Instant.now();
154+
}
155+
}
156+
```
157+
158+
---
159+
160+
## 4. Resource Safety: try-with-resources
161+
162+
Always wrap resource declarations implementing `AutoCloseable` in `try-with-resources` statements to prevent heap memory leak traps.
163+
164+
```java
165+
package org.spacecraftsoftware.telemetry;
166+
167+
import java.io.BufferedReader;
168+
import java.io.FileReader;
169+
import java.io.IOException;
170+
import java.nio.file.Path;
171+
172+
public class TelemetryFileReader {
173+
174+
public String readFirstTelemetryLine(Path filePath) throws IOException {
175+
// CRITICAL: Banish resource leaks by ensuring try-with-resources handles autoclosing
176+
try (var fileReader = new FileReader(filePath.toFile());
177+
var bufferedReader = new BufferedReader(fileReader)) {
178+
179+
String line = bufferedReader.readLine();
180+
return line != null ? line : "";
181+
}
182+
}
183+
}
184+
```
185+
186+
---
187+
188+
## 5. Sequenced Collections and Record Constants
189+
190+
Java 21 introduces Sequenced Collections, standardizing collection retrieval order. Combine with record classes for clean, type-safe data access.
191+
192+
```java
193+
package org.spacecraftsoftware.telemetry;
194+
195+
import java.util.LinkedHashSet;
196+
import java.util.SequencedSet;
197+
198+
public class SequenceManager {
199+
200+
public record SensorReading(int sensorId, double value) {}
201+
202+
public void processSequencedReadings() {
203+
SequencedSet<SensorReading> readings = new LinkedHashSet<>();
204+
readings.add(new SensorReading(1, 12.3));
205+
readings.add(new SensorReading(2, 45.6));
206+
readings.add(new SensorReading(3, 78.9));
207+
208+
// Retrieve first and last elements cleanly
209+
SensorReading first = readings.getFirst();
210+
SensorReading last = readings.getLast();
211+
212+
System.out.println("First reading: " + first.value());
213+
System.out.println("Last reading: " + last.value());
214+
215+
// Traverse in reverse order
216+
for (SensorReading r : readings.reversed()) {
217+
System.out.println("Reversed: " + r.sensorId());
218+
}
219+
}
220+
}
221+
```
222+
223+
---
224+
225+
## 6. Testing: JUnit 5 Integration
226+
227+
Write structured test validations using JUnit 5 assertions.
228+
229+
```java
230+
package org.spacecraftsoftware.telemetry;
231+
232+
import org.junit.jupiter.api.Test;
233+
import java.io.IOException;
234+
import java.nio.file.Files;
235+
import java.nio.file.Path;
236+
import java.util.List;
237+
238+
import static org.junit.jupiter.api.Assertions.*;
239+
240+
class TelemetryWorkerTest {
241+
242+
@Test
243+
void testVirtualThreadExecution() throws Exception {
244+
VirtualThreadProcessor processor = new VirtualThreadProcessor();
245+
List<String> sensors = List.of("GPS_01", "GYRO_02", "TEMP_03");
246+
247+
List<Double> results = processor.fetchAllTelemetry(sensors);
248+
249+
assertNotNull(results);
250+
assertEquals(3, results.size());
251+
for (Double reading : results) {
252+
assertTrue(reading >= 0.0 && reading <= 100.0);
253+
}
254+
}
255+
256+
@Test
257+
void testTelemetryFileReaderLeaks() throws IOException {
258+
Path tempFile = Files.createTempFile("telemetry_mock", ".log");
259+
Files.writeString(tempFile, "SYSTEM_OK\nDETAILS_MOCK");
260+
261+
TelemetryFileReader reader = new TelemetryFileReader();
262+
String result = reader.readFirstTelemetryLine(tempFile);
263+
264+
assertEquals("SYSTEM_OK", result);
265+
Files.delete(tempFile);
266+
}
267+
}
268+
```

0 commit comments

Comments
 (0)