Skip to content

fix: use ConcurrentHashMap for Version.VERSION2INT to prevent concurrent corruption#16171

Open
daguimu wants to merge 1 commit intoapache:3.3from
daguimu:fix/version2int-concurrent-hashmap
Open

fix: use ConcurrentHashMap for Version.VERSION2INT to prevent concurrent corruption#16171
daguimu wants to merge 1 commit intoapache:3.3from
daguimu:fix/version2int-concurrent-hashmap

Conversation

@daguimu
Copy link

@daguimu daguimu commented Mar 25, 2026

Problem

Version.VERSION2INT uses a plain HashMap that is accessed concurrently from the RPC hot path:

private static final Map<String, Integer> VERSION2INT = new HashMap<>(); // NOT thread-safe

public static int getIntVersion(String version) {
    Integer v = VERSION2INT.get(version);  // concurrent read
    if (v == null) {
        v = parseInt(version);
        VERSION2INT.put(version, v);       // concurrent write
    }
    return v;
}

This is called via isSupportResponseAttachment() on every RPC call to check protocol compatibility.

Impact

Concurrent put() during HashMap internal resize can corrupt the hash table's bucket chain, causing threads to hang permanently in an infinite loop during get() — a well-documented JDK issue with unsynchronized HashMap access. This is a classic production incident pattern that is difficult to diagnose.

Root Cause

HashMap was used where ConcurrentHashMap is required. The code comment on the field even notes it is used for performance ("int compare expect to has higher performance than string"), but the collection itself is not thread-safe.

Fix

Replace new HashMap<>() with new ConcurrentHashMap<>(). The check-then-act pattern in getIntVersion() is acceptable because:

  1. The computation is idempotent (same version string always produces the same int)
  2. Worst case under concurrent miss: two threads compute and put the same value — no data loss or corruption with ConcurrentHashMap

Tests Added

  • testGetIntVersionConcurrency — 10 threads × 1000 iterations calling getIntVersion with various version strings concurrently, verifying consistent results

All 9 tests in VersionTest pass.

Impact

  • 1-line production change: HashMapConcurrentHashMap
  • Zero behavioral change
  • Eliminates risk of thread hangs in the RPC protocol path

…ent corruption

VERSION2INT uses a plain HashMap that is read and written concurrently
from the RPC hot path (isSupportResponseAttachment is checked on every
call). Concurrent put() during HashMap resize can corrupt the internal
hash table, causing threads to hang in infinite loops.
@daguimu daguimu force-pushed the fix/version2int-concurrent-hashmap branch from 178e685 to f992a6a Compare March 25, 2026 12:11
@codecov-commenter
Copy link

codecov-commenter commented Mar 25, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 60.80%. Comparing base (63fe8c3) to head (f992a6a).
⚠️ Report is 1 commits behind head on 3.3.

Additional details and impacted files
@@             Coverage Diff              @@
##                3.3   #16171      +/-   ##
============================================
- Coverage     60.81%   60.80%   -0.02%     
+ Complexity    11765    11753      -12     
============================================
  Files          1953     1953              
  Lines         89118    89118              
  Branches      13444    13444              
============================================
- Hits          54197    54188       -9     
- Misses        29364    29369       +5     
- Partials       5557     5561       +4     
Flag Coverage Δ
integration-tests-java21 32.15% <100.00%> (-0.02%) ⬇️
integration-tests-java8 32.23% <100.00%> (-0.09%) ⬇️
samples-tests-java21 32.19% <100.00%> (+<0.01%) ⬆️
samples-tests-java8 29.72% <100.00%> (-0.03%) ⬇️
unit-tests-java11 59.06% <100.00%> (+0.02%) ⬆️
unit-tests-java17 58.51% <100.00%> (-0.03%) ⬇️
unit-tests-java21 58.52% <100.00%> (-0.01%) ⬇️
unit-tests-java25 58.45% <100.00%> (-0.07%) ⬇️
unit-tests-java8 59.03% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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