Repository navigation
v1.1.0
What's New in v1.1.0
Immutable JDK type support
Freeze/restore now correctly handles immutable JDK types whose final fields can't be set via Objenesis. Each type is captured via JDI field reads and reconstructed via parse/valueOf on restore.
Supported types: BigDecimal, BigInteger, UUID, LocalDate, LocalTime, LocalDateTime, Instant, Duration, ZonedDateTime, OffsetDateTime, Period, Year, YearMonth, MonthDay, ZoneOffset, ZoneId, URI
Enum support
Enum constants are captured by name and restored via Enum.valueOf(), preserving:
==identity (critical for switch statements and comparisons)ordinal()values and custom enum fields- Use as
HashMap/HashSetkeys - Works for both user-defined enums and JDK enums like
TimeUnit - Correctly handles Java 8 enum constants with method overrides (anonymous subclasses)
Fail-fast validation (UncapturableTypeException)
freeze() now throws UncapturableTypeException immediately when it encounters a type that cannot be restored correctly:
| Type | Advice |
|---|---|
Optional |
Use T directly with null instead |
| Unmodifiable collections | Use mutable collections |
Thread, ClassLoader |
Remove from captured state |
| I/O / network types | Close or remove before freezing |
Pattern |
Store pattern string, recompile after restore |
JDI reliability improvements
- Double-suspend — All JDI suspend/resume operations use suspend count = 2 for resilience against spurious JDI resume events
- Event draining — Pending JDI events from prior freeze/restore cycles are drained before each suspend to prevent races
- Exponential backoff — Retry with up to 10 attempts (50ms → 800ms backoff) on
InvalidStackFrameException - Pre-load classes — All classes referenced by snapshot locals are force-loaded before frame manipulation, preventing
ClassNotLoadedExceptionduring restore - JDWP bypass for Java 8 — When JDI's classloader lookup fails for bootstrap-loaded classes on Java 8, the library sets slot values directly via JDWP reflection, bypassing the broken client-side type check
- Automatic class loading — Classes referenced by local variables are automatically force-loaded via
Class.forName()through JDI when aClassNotLoadedExceptionis encountered during restore
Bug fixes
- Fixed boxed primitives (Integer, Long, etc.) inside collections losing their values during restore
- Fixed latch deadlock when freeze worker thread completed before caller reached wait
- Fixed JDI connection races during concurrent freeze attempts
- Fixed field mutations being duplicated during skip-pass replay
- Fixed resume stub using dummy receiver instead of heap-restored object
CI coverage expansion
Test matrix now covers 7 JDK versions × 3 platforms = 21 combinations:
- JDK versions: 8, 9, 11, 17 (LTS), 21 (LTS), 24, 25
- Platforms: Ubuntu, macOS (ARM), Windows
- 127 unit tests + 35 integration tests per combination