Skip to content

Fix RAC IllegalAccessError in Atomic{Long,Integer,Boolean} constructor specs - #29

Closed
bernardladenthin wants to merge 1 commit into
OpenJML:master-21from
bernardladenthin:fix/rac-atomiclong-private-value-access
Closed

bernardladenthin wants to merge 1 commit into
OpenJML:master-21from
bernardladenthin:fix/rac-atomiclong-private-value-access

Conversation

@bernardladenthin

@bernardladenthin bernardladenthin commented Sep 13, 2026 •

Copy link
Copy Markdown
Contributor

The Atomic{Long,Integer,Boolean} constructor specs reference the private java.base
field value in unguarded clauses (ensures value == v / == 0). RAC checks them at the
call site; spec_public is only honoured for classes RAC compiles itself
(JmlAssertionAdder flips the flag to public), so the client emits
getfield AtomicLong.value and throws IllegalAccessError on any new AtomicLong()
(also on OpenJML's own JVM; --add-opens does not help, it only affects reflection).

Fix, following the existing idioms of these files:

  • AtomicLong, AtomicInteger: ensures get() == v (as set() / intValue() already do).
    ESC-equivalent, since get() has -RAC ensures \result == value.
  • AtomicBoolean: -RAC ensures value == (v ? 1:0) + +RAC ensures get() == v
    (as get() does). A plain get() == v would lose value ∈ {0,1}:
    new AtomicBoolean(true).compareAndSet(true, false) is then no longer provable.

Verified with 21.0.27 (Windows): RAC red before / green after for all three classes;
ESC output unchanged. Tests: OpenJML/OpenJML#982 (testspecs, SpecsEsc + SpecsRac).
Base: master-21 (the branch OpenJML 21.x builds against).

Found via OpenJML RAC on https://github.com/bernardladenthin/streambuffer

@bernardladenthin
bernardladenthin force-pushed the fix/rac-atomiclong-private-value-access branch from ade0017 to 4ebda9c Compare September 30, 2026 20:55
@bernardladenthin bernardladenthin changed the title AtomicLong: use get() in ctor specs to fix RAC IllegalAccessError Fix RAC IllegalAccessError in Atomic{Long,Integer,Boolean} constructor specs Sep 30, 2026
@bernardladenthin
bernardladenthin changed the base branch from master to master-21 September 30, 2026 20:57
davidcok added a commit that referenced this pull request Oct 5, 2026
…AndSet omitted

- RAC: the constructors, set and lazySet state their postconditions on the
  private field value only for ESC (-RAC), and through get() for RAC (+RAC),
  extending #29; get() is a helper.
- AtomicLong.getAndAdd: ensures value == \old(value) + v (was value == v,
  which let ESC prove false results).
- AtomicLong.accumulateAndGet: \result is the new value (was \old(value)).
- AtomicLong.getAndUpdate: ensures \result == \old(value) (was 'true').
- AtomicInteger/AtomicLong.lazySet: the same postcondition as set (was 'true').
- weakCompareAndSet is omitted from all three: it is deprecated (since Java 9),
  and its spec claimed it always succeeds when the value matches, which Java
  does not guarantee.

Tested by OpenJMLTest/testspecs java-util-concurrent-atomic-* (SpecsEsc and
SpecsRac).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@davidcok

davidcok commented Oct 5, 2026

Copy link
Copy Markdown
Member

Merged via dev-21: this commit (4ebda9c) is on Specs dev-21, where c365293 extends it (RAC-safe Atomic{Boolean,Integer,Long} specs, spec fixes, weakCompareAndSet omitted). OpenJML's testspecs cases from OpenJML/OpenJML#982 pass with it (SpecsEsc, SpecsRac, SpecsBase). It will reach master-21 with the next merge of dev-21.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants