# False negative java:S2168: not reported when the outer null check is written \`!(helper != null)\`

**URL:** <https://community.sonarsource.com/t/false-negative-java-not-reported-when-the-outer-null-check-is-written-helper-null/190766>\
**Category:** Report False-positive / False-negative...\
**Tags:** java\
**Created:** [October 31, 2026, 5:30pm UTC](https://community.sonarsource.com/t/false-negative-java-not-reported-when-the-outer-null-check-is-written-helper-null/190766 "2026-10-31T17:30:57Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![MarkLee131](https://dub1.discourse-cdn.com/sonarsource/user_avatar/community.sonarsource.com/marklee131/32/77010_2.png) [@MarkLee131](https://community.sonarsource.com/u/MarkLee131)\
**Post date:** [October 31, 2026, 5:30pm UTC](https://community.sonarsource.com/t/false-negative-java-not-reported-when-the-outer-null-check-is-written-helper-null/190766/1 "2026-10-31T17:30:57Z")

</div>

**Product/version:** SonarQube Community Build 26.7.0.124771, sonar-scanner 8.1.0.6389

**Language:** Java

**Rule:** java:S2168

**Issue:**

S2168 reports the double-checked locking on the non-volatile field `helper` in `seed/Dcl.java`. In `variant/Dcl.java` the outer null check is written `!(helper != null)` instead of `helper == null`, everything else is the same, and nothing is reported. `!(!(helper == null))` isn’t reported either.

`DoubleCheckedLockingCheck.isIfFieldEqNull` only treats an `if` as a field null check when the condition is `EQUAL_TO` with a null literal on one side (`DoubleCheckedLockingCheck.java:88-103` at 8.34.0.44906, unchanged at 88.0.0.3367). It never unwraps `!`, so the outer `if` isn’t pushed on the field stack and the inner check finds no matching outer one.

PMD’s DoubleCheckedLocking had the same gap and now accepts negated null checks (pmd#6900, fixed in 7.27.0). Error Prone accepted the same report (error-prone#5963).

**Reproducer:**

`seed/Dcl.java`:

```java
public class Dcl {
    private Helper helper;

    Helper getHelper() {
        if (helper == null) { // S2168 reported on the synchronized below
            synchronized (this) {
                if (helper == null) {
                    helper = new Helper();
                }
            }
        }
        return helper;
    }

    static class Helper {
        int x;
    }
}

```

`variant/Dcl.java`:

```java
public class Dcl {
    private Helper helper;

    Helper getHelper() {
        if (!(helper != null)) { // the same outer check; nothing reported
            synchronized (this) {
                if (helper == null) {
                    helper = new Helper();
                }
            }
        }
        return helper;
    }

    static class Helper {
        int x;
    }
}

```

**Expected behavior:**

S2168 (“Remove this dangerous instance of double-checked locking.”) on the `synchronized` keyword in `variant/Dcl.java`, as in `seed/Dcl.java`.

**How to reproduce:**

```auto
# one project per file
sonar-scanner -Dsonar.projectKey=<key> -Dsonar.sources=. \
    -Dsonar.java.binaries=. -Dsonar.scm.disabled=true

```

**Output** of the commands above:

```plaintext
### SonarQube Community Build 26.9.0.129388 (sonar-java 8.41.0.47177), server reports 26.9.0.129388, default Sonar way profile rule: S2168

--- SEED -- expected: reported (seed/)
    java:S1220 line - Move this file to a named package.
    java:S2168 line 6 Remove this dangerous instance of double-checked locking. <== S2168
    [S2168: 1]

--- VARIANT -- expected: reported; actual: not reported (variant/)
    java:S1220 line - Move this file to a named package.
    java:S1940 line 5 Use the opposite operator ("==") instead.
    [S2168: 0]

```

---

<div class="post-metadata">

**Author:** ![david.schroeter](https://avatars.discourse-cdn.com/v4/letter/d/dfb087/32.png) [@david.schroeter](https://community.sonarsource.com/u/david.schroeter)\
**Post date:** [November 2, 2026, 1:12pm UTC](https://community.sonarsource.com/t/false-negative-java-not-reported-when-the-outer-null-check-is-written-helper-null/190766/3 "2026-11-02T13:12:01Z")

</div>

Hi @MarkLee131!

Thank you for reporting this issue and providing a clear reproducer.

I have created a ticket to track it here: **[SONARJAVA-7282](https://sonarsource.atlassian.net/browse/SONARJAVA-7282)**

Thanks again for your contribution!

David
