daguimu opened a new pull request, #16169:
URL: https://github.com/apache/dubbo/pull/16169

   ## Problem
   
   `BitList.emptyList()` returns a shared static singleton instance. Since 
`BitList` is mutable (supports `add()`, `addToTailList()`, `and()`, etc.), any 
caller that modifies the returned "empty" list inadvertently mutates the 
singleton, contaminating all subsequent callers.
   
   In `AbstractDirectory`, the `invokers` field is initialized with 
`BitList.emptyList()`. When the first interface's invokers are added, they 
pollute the shared singleton. When a second interface later calls 
`BitList.emptyList()`, it receives a list already containing the first 
interface's invokers, causing traffic to be routed to the wrong instances and 
resulting in `NoSuchMethodError`.
   
   ## Root Cause
   
   ```java
   // Shared mutable singleton - any mutation affects all callers
   private static final BitList emptyList = new 
BitList(Collections.emptyList());
   
   public static <T> BitList<T> emptyList() {
       return emptyList; // returns the SAME instance every time
   }
   ```
   
   ## Fix
   
   Return a new `BitList` instance on each call to `emptyList()`, consistent 
with how mutable collections should behave:
   
   ```java
   public static <T> BitList<T> emptyList() {
       return new BitList<>(Collections.emptyList());
   }
   ```
   
   ## Tests Added
   
   - `testEmptyListReturnsIndependentInstances` — Verifies each call returns a 
distinct object
   - `testEmptyListMutationDoesNotAffectOtherEmptyList` — Reproduces the exact 
bug: adding elements to one empty list must not affect another (the core 
scenario from #16131)
   - `testEmptyListTailListMutationDoesNotAffectOtherEmptyList` — Verifies tail 
list mutations are also isolated
   - `testEmptyListIsInitiallyEmpty` — Confirms the returned list starts truly 
empty
   
   All 26 tests in `BitListTest` pass.
   
   ## Impact
   
   - Minimal change: removes 1 static field, modifies 1 method (3 lines changed 
in production code)
   - No behavioral change for callers — they get the same empty `BitList`, just 
a fresh instance
   - No reference equality (`==`) checks exist against `BitList.emptyList()` in 
the codebase
   - Fixes a critical production bug where cross-interface invoker leakage 
causes `NoSuchMethodError`
   
   Fixes #16131


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to