Repository navigation
v1.3.5
v1.3.5 — Major Refactoring, Audit Fixes, and Robustness Improvements
Architecture Refactoring
ThreadRestorer decomposition (Stages 1–4):
- Extract
SnapshotValidator— bytecode/structure hash validation (Stage 1) - Extract
ReflectionHelpers— method lookup, descriptor matching, bottom frame invocation (Stage 2a–2e) - Extract
JdiValueConverter— stateless snapshot ObjectRef → JDI Value conversion (Stage 3) - Extract
JdiLocalSetter— JDI local variable setting with frame matching, GC pinning, class preloading (Stage 4a–4c) - ThreadRestorer reduced from ~1150 lines to ~375 lines
PrologueInjector decomposition (v1.3.1):
- Extract
OperandStackSimulator— JVM operand stack simulation for type tracking - Extract
PrologueEmitter— replay prologue bytecode emission - Extract
PrologueTypes— shared data types - PrologueInjector reduced from ~1300 lines to ~280 lines
Bug Fixes
- FrameSnapshot equals/hashCode/toString —
lambdaBridgeInterfacefield was missing from all three methods, causing two snapshots differing only in lambda bridge interface to compare as equal - Snapshot handler deadlock — moved
handler.accept()afterthreadRef.resume()so the handler no longer runs while the frozen thread is JDI-suspended; eliminates deadlock if handler acquires locks held by the frozen thread - FreezeFlag thread ID reuse — replaced
Set<Long>(thread IDs) withSet<Thread>using IdentityHashMap; eliminates false positives from JVM thread ID recycling - Broken slot reflection —
captureLocalsusedgetMethod("slot")on a package-private method, which always threwNoSuchMethodExceptionand silently defaulted every variable's slot to 0; removed the dead reflection entirely (restore matches by name, not slot)
Dead Code Removal
- Removed 4 dead
catch(Exception ignored)blocks in ThreadFreezer that were confirmed to never fire by running all 258 tests without them - Removed dead if/else branch in
HeapRestorer.populateArray(both branches identical) - Removed unused
isInfrastructureFramestatic import from ThreadRestorer
Enterprise Improvements
- Configurable timeouts via system properties:
durable.freeze.timeout.ms(default 30s) — caller thread wait for freeze workerdurable.jdi.wait.timeout.ms(default 30s) — JDI worker wait for replay threaddurable.restore.timeout.seconds(default 300s) — go-latch wait (existing)
CI
- Removed ubuntu JDK 10 from matrix (intermittent Zulu failures unrelated to our code)
- Bumped actions/checkout, actions/setup-java, actions/cache from v4 to v5 (Node.js 24)
Tests
All 258 tests pass (215 unit + 43 E2E) across JDK 8–25 on Linux, macOS, and Windows.