[FB-Discuss] Mutable Key Bug

Jon Schewe jpschewe at mtu.net
Wed Aug 18 07:27:28 EDT 2010

 Actually you won't. Sam is right and I've run into this. If the key of
a HashMap is a mutable object and the object is mutated after it's used
as a key you effectively loose the value. This is because when you put
the value in it was put in a bin based on the first hashcode, say 2.
Then the key is mutated and you use that same reference to lookup the
value in the HashMap, except now the hashcode of the key is 6. Here the
HashMap looks in bin 6 and then uses equals on the list of things in
that bin to find the value. Unfortunately nothing will match because the
value is actually in bin 2. This is a real bug that would be great for
FindBugs to find, but I'm not sure how you could check for a mutable
object being a key. The hard part is determining if an object is mutable.

On 8/18/10 3:16 AM, Andrei Loskutov wrote:
> Hi Sam,
> I do not see any bug there except that your cache is badly implemented.
> For the same key you get the same value, independently on the fact that the key's hashcode is changed. That's ok, as the hashCode() and equals() are properly implemented for HashSet class. If you have expected that the second call should return "[6]", then you should not only call clear() on a key but also remove the cached [1,2,3] value from the objectMap. So in such case you have to change your cache implementation, if it should be cleaned up as soon as the key is modified.
> Background: the map key is a HashSet, and the value is a (cached) String instance. So even if hashCode() of a changed HashSet is changed, the map still can retrieve the previously cached String "[1,2,3]" for the changed key, as equals() of the key is also changed. This works as designed by the code and is in sync with the Map API. Anything else is a bug :-)
> -------- Original-Nachricht --------
>> Datum: Tue, 17 Aug 2010 17:45:31 -0700 (PDT)
>> Von: Sam Beroz <samberoz at yahoo.com>
>> An: findbugs-discuss at cs.umd.edu
>> Betreff: [FB-Discuss] Mutable Key Bug
>> I recently ran into the following bug as part of an attempt at creating a
>> cache 
>> and was wondering if it could be detected by FindBugs in the future:
>> import java.util.HashMap;
>> import java.util.HashSet;
>> import java.util.Map;
>> import java.util.Set;
>> public class BugTest {
>>     private Map<Set<Integer>, String> objectMap = new
>> HashMap<Set<Integer>, 
>> String>();
>>     private String lookup(Set<Integer> key){
>>         String value = objectMap.get(key);
>>         if(value == null){
>>             value = key.toString();
>>             objectMap.put(key, value); //value associated with mutable
>> key!
>>         }
>>         return value;
>>     }
>>     public static void main(String[] argv){
>>         Set<Integer> key = new HashSet<Integer>();
>>         key.add(1);
>>         key.add(2);
>>         key.add(3);
>>         BugTest tester = new BugTest();
>>         String value = tester.lookup(key);
>>         System.out.println("key: " + key + " maps to value: " + value);
>>         int hashCode = key.hashCode();
>>         key.clear(); //mutable key is modified!
>>         key.add(hashCode); //new key will hash into the same bin
>>         value = tester.lookup(key);
>>         System.out.println("key: " + key + " maps to value: " + value);
>>     }
>> }
>> The output is:
>> key: [1, 2, 3] maps to value: [1, 2, 3]
>> key: [6] maps to value: [1, 2, 3]

Jon Schewe | http://mtu.net/~jpschewe
If you see an attachment named signature.asc, this is my digital
signature. See http://www.gnupg.org for more information.

More information about the Findbugs-discuss mailing list