You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Andrew Sunde (JIRA)" <ji...@apache.org> on 2010/03/19 19:54:27 UTC

[jira] Created: (BEANUTILS-373) CLONE - MethodUtils is not thread safe because WeakFastHashMap which uses WeakHashMap is not thread-safe.

CLONE - MethodUtils is not thread safe because WeakFastHashMap which uses WeakHashMap is not thread-safe.
---------------------------------------------------------------------------------------------------------

                 Key: BEANUTILS-373
                 URL: https://issues.apache.org/jira/browse/BEANUTILS-373
             Project: Commons BeanUtils
          Issue Type: Bug
          Components: Bean / Property Utils
    Affects Versions: 1.7.0
         Environment: Weblogic 9.2 on Linux, but should not be relevant
            Reporter: Andrew Sunde
            Assignee: Niall Pemberton
             Fix For: 1.8.0


The problem lies in the class org.apache.commons.beanutils.MethodUtils. This class is keeping a global cache in a non synchronized WeakHashMap. WeakHashMap is not thread safe and required external synchronization. The lack of synchronization can cause corruption and the WeakHashMap.get() method to go into an infinite loop.

Googling "WeakHashMap infinite loop" returns many cases of similar problem with WeakHashMap. The solution is to decorate the WeakHashMap in a synchronized Map as described in this thread:
http://dev.eclipse.org/mhonarc/lists/aspectj-users/msg08824.html

The modification to make the MethodUtils cache thread safe is a one line change. 
Before: 
private static WeakHashMap cache = new WeakHashMap();

After: 
private static Map cache = Collections.synchronizedMap(new WeakHashMap());

Example of thread dump

"ExecuteThread: '0' for queue: 'weblogic.kernel.Default'" id=13 idx=0x3c tid=5905 prio=5 alive, daemon
    at org/apache/commons/beanutils/MethodUtils$MethodDescriptor.equals(MethodUtils.java:828)[optimized]
    at java/util/WeakHashMap.eq(WeakHashMap.java:254)[inlined]
    at java/util/WeakHashMap.get(WeakHashMap.java:345)[optimized]
    at org/apache/commons/beanutils/MethodUtils.getMatchingAccessibleMethod(MethodUtils.java:530)[optimized]
    at org/apache/commons/beanutils/MethodUtils.invokeMethod(MethodUtils.java:209)[inlined]
::::

"ExecuteThread: '1' for queue: 'weblogic.kernel.Default'" id=14 idx=0x40 tid=5906 prio=5 alive, daemon
    at org/apache/commons/beanutils/MethodUtils$MethodDescriptor.equals(MethodUtils.java:833)[optimized]
    at java/util/WeakHashMap.eq(WeakHashMap.java:254)[inlined]
    at java/util/WeakHashMap.get(WeakHashMap.java:345)[optimized]
    at org/apache/commons/beanutils/MethodUtils.getMatchingAccessibleMethod(MethodUtils.java:530)[optimized]
    at org/apache/commons/beanutils/MethodUtils.invokeMethod(MethodUtils.java:209)[inlined]
:::
"ExecuteThread: '2' for queue: 'weblogic.kernel.Default'" id=15 idx=0x44 tid=5907 prio=5 alive, daemon
    at org/apache/commons/beanutils/MethodUtils$MethodDescriptor.equals(MethodUtils.java:833)[optimized]
    at java/util/WeakHashMap.eq(WeakHashMap.java:254)[inlined]
    at java/util/WeakHashMap.get(WeakHashMap.java:345)[optimized]
    at org/apache/commons/beanutils/MethodUtils.getMatchingAccessibleMethod(MethodUtils.java:530)[optimized]
    at org/apache/commons/beanutils/MethodUtils.invokeMethod(MethodUtils.java:209)[inlined]




-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Updated: (BEANUTILS-373) CLONE - MethodUtils is not thread safe because WeakFastHashMap which uses WeakHashMap is not thread-safe.

Posted by "Andrew Sunde (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/BEANUTILS-373?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Andrew Sunde updated BEANUTILS-373:
-----------------------------------

    Description: 
The problem lies in the class org.apache.commons.beanutils.MethodUtils. This class is keeping a global cache in a non synchronized WeakFastHashMap (which claims to be syncronized). When operating in Fast mode (which is what the WeakFastHashMap is set to after it is created), it then access the underlining WeakHashMap without synchronization. Therefore this can lead to a corruption in the underlining HashMap.

See the description of the WeakHashMap javadoc:
>From Java Sun: "
Like most collection classes, this class is not synchronized. A synchronized WeakHashMap may be constructed using the Collections.synchronizedMap  method. 
....
The behavior of the WeakHashMap class depends in part upon the actions of the garbage collector, so several familiar (though not required) Map invariants do not hold for this class. Because the garbage collector may discard keys at any time, a WeakHashMap may behave as though an unknown thread is silently removing entries.
"

Therefore even if you are doing a "get" from the hashmap, there is a chance that you could get a corrupted hashmap because the garbage collector could be changing the hashmap on the fly. This could lead to threads getting stuck in an infinite loop.


The modification to make the MethodUtils cache thread safe is a one line change. 
Before: 
private static WeakFastHashMap cache = new WeakFastHashMap();

After: 
private static Map cache = Collections.synchronizedMap(new WeakHashMap());





  was:
The problem lies in the class org.apache.commons.beanutils.MethodUtils. This class is keeping a global cache in a non synchronized WeakHashMap. WeakHashMap is not thread safe and required external synchronization. The lack of synchronization can cause corruption and the WeakHashMap.get() method to go into an infinite loop.

Googling "WeakHashMap infinite loop" returns many cases of similar problem with WeakHashMap. The solution is to decorate the WeakHashMap in a synchronized Map as described in this thread:
http://dev.eclipse.org/mhonarc/lists/aspectj-users/msg08824.html

The modification to make the MethodUtils cache thread safe is a one line change. 
Before: 
private static WeakHashMap cache = new WeakHashMap();

After: 
private static Map cache = Collections.synchronizedMap(new WeakHashMap());

Example of thread dump

"ExecuteThread: '0' for queue: 'weblogic.kernel.Default'" id=13 idx=0x3c tid=5905 prio=5 alive, daemon
    at org/apache/commons/beanutils/MethodUtils$MethodDescriptor.equals(MethodUtils.java:828)[optimized]
    at java/util/WeakHashMap.eq(WeakHashMap.java:254)[inlined]
    at java/util/WeakHashMap.get(WeakHashMap.java:345)[optimized]
    at org/apache/commons/beanutils/MethodUtils.getMatchingAccessibleMethod(MethodUtils.java:530)[optimized]
    at org/apache/commons/beanutils/MethodUtils.invokeMethod(MethodUtils.java:209)[inlined]
::::

"ExecuteThread: '1' for queue: 'weblogic.kernel.Default'" id=14 idx=0x40 tid=5906 prio=5 alive, daemon
    at org/apache/commons/beanutils/MethodUtils$MethodDescriptor.equals(MethodUtils.java:833)[optimized]
    at java/util/WeakHashMap.eq(WeakHashMap.java:254)[inlined]
    at java/util/WeakHashMap.get(WeakHashMap.java:345)[optimized]
    at org/apache/commons/beanutils/MethodUtils.getMatchingAccessibleMethod(MethodUtils.java:530)[optimized]
    at org/apache/commons/beanutils/MethodUtils.invokeMethod(MethodUtils.java:209)[inlined]
:::
"ExecuteThread: '2' for queue: 'weblogic.kernel.Default'" id=15 idx=0x44 tid=5907 prio=5 alive, daemon
    at org/apache/commons/beanutils/MethodUtils$MethodDescriptor.equals(MethodUtils.java:833)[optimized]
    at java/util/WeakHashMap.eq(WeakHashMap.java:254)[inlined]
    at java/util/WeakHashMap.get(WeakHashMap.java:345)[optimized]
    at org/apache/commons/beanutils/MethodUtils.getMatchingAccessibleMethod(MethodUtils.java:530)[optimized]
    at org/apache/commons/beanutils/MethodUtils.invokeMethod(MethodUtils.java:209)[inlined]





> CLONE - MethodUtils is not thread safe because WeakFastHashMap which uses WeakHashMap is not thread-safe.
> ---------------------------------------------------------------------------------------------------------
>
>                 Key: BEANUTILS-373
>                 URL: https://issues.apache.org/jira/browse/BEANUTILS-373
>             Project: Commons BeanUtils
>          Issue Type: Bug
>          Components: Bean / Property Utils
>    Affects Versions: 1.8.2
>         Environment: Weblogic 9.2 on Linux, but should not be relevant
>            Reporter: Andrew Sunde
>            Assignee: Niall Pemberton
>
> The problem lies in the class org.apache.commons.beanutils.MethodUtils. This class is keeping a global cache in a non synchronized WeakFastHashMap (which claims to be syncronized). When operating in Fast mode (which is what the WeakFastHashMap is set to after it is created), it then access the underlining WeakHashMap without synchronization. Therefore this can lead to a corruption in the underlining HashMap.
> See the description of the WeakHashMap javadoc:
> From Java Sun: "
> Like most collection classes, this class is not synchronized. A synchronized WeakHashMap may be constructed using the Collections.synchronizedMap  method. 
> ....
> The behavior of the WeakHashMap class depends in part upon the actions of the garbage collector, so several familiar (though not required) Map invariants do not hold for this class. Because the garbage collector may discard keys at any time, a WeakHashMap may behave as though an unknown thread is silently removing entries.
> "
> Therefore even if you are doing a "get" from the hashmap, there is a chance that you could get a corrupted hashmap because the garbage collector could be changing the hashmap on the fly. This could lead to threads getting stuck in an infinite loop.
> The modification to make the MethodUtils cache thread safe is a one line change. 
> Before: 
> private static WeakFastHashMap cache = new WeakFastHashMap();
> After: 
> private static Map cache = Collections.synchronizedMap(new WeakHashMap());

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Updated: (BEANUTILS-373) CLONE - MethodUtils is not thread safe because WeakFastHashMap which uses WeakHashMap is not thread-safe.

Posted by "Andrew Sunde (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/BEANUTILS-373?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Andrew Sunde updated BEANUTILS-373:
-----------------------------------

        Fix Version/s:     (was: 1.8.0)
    Affects Version/s:     (was: 1.7.0)
                       1.8.2

> CLONE - MethodUtils is not thread safe because WeakFastHashMap which uses WeakHashMap is not thread-safe.
> ---------------------------------------------------------------------------------------------------------
>
>                 Key: BEANUTILS-373
>                 URL: https://issues.apache.org/jira/browse/BEANUTILS-373
>             Project: Commons BeanUtils
>          Issue Type: Bug
>          Components: Bean / Property Utils
>    Affects Versions: 1.8.2
>         Environment: Weblogic 9.2 on Linux, but should not be relevant
>            Reporter: Andrew Sunde
>            Assignee: Niall Pemberton
>
> The problem lies in the class org.apache.commons.beanutils.MethodUtils. This class is keeping a global cache in a non synchronized WeakHashMap. WeakHashMap is not thread safe and required external synchronization. The lack of synchronization can cause corruption and the WeakHashMap.get() method to go into an infinite loop.
> Googling "WeakHashMap infinite loop" returns many cases of similar problem with WeakHashMap. The solution is to decorate the WeakHashMap in a synchronized Map as described in this thread:
> http://dev.eclipse.org/mhonarc/lists/aspectj-users/msg08824.html
> The modification to make the MethodUtils cache thread safe is a one line change. 
> Before: 
> private static WeakHashMap cache = new WeakHashMap();
> After: 
> private static Map cache = Collections.synchronizedMap(new WeakHashMap());
> Example of thread dump
> "ExecuteThread: '0' for queue: 'weblogic.kernel.Default'" id=13 idx=0x3c tid=5905 prio=5 alive, daemon
>     at org/apache/commons/beanutils/MethodUtils$MethodDescriptor.equals(MethodUtils.java:828)[optimized]
>     at java/util/WeakHashMap.eq(WeakHashMap.java:254)[inlined]
>     at java/util/WeakHashMap.get(WeakHashMap.java:345)[optimized]
>     at org/apache/commons/beanutils/MethodUtils.getMatchingAccessibleMethod(MethodUtils.java:530)[optimized]
>     at org/apache/commons/beanutils/MethodUtils.invokeMethod(MethodUtils.java:209)[inlined]
> ::::
> "ExecuteThread: '1' for queue: 'weblogic.kernel.Default'" id=14 idx=0x40 tid=5906 prio=5 alive, daemon
>     at org/apache/commons/beanutils/MethodUtils$MethodDescriptor.equals(MethodUtils.java:833)[optimized]
>     at java/util/WeakHashMap.eq(WeakHashMap.java:254)[inlined]
>     at java/util/WeakHashMap.get(WeakHashMap.java:345)[optimized]
>     at org/apache/commons/beanutils/MethodUtils.getMatchingAccessibleMethod(MethodUtils.java:530)[optimized]
>     at org/apache/commons/beanutils/MethodUtils.invokeMethod(MethodUtils.java:209)[inlined]
> :::
> "ExecuteThread: '2' for queue: 'weblogic.kernel.Default'" id=15 idx=0x44 tid=5907 prio=5 alive, daemon
>     at org/apache/commons/beanutils/MethodUtils$MethodDescriptor.equals(MethodUtils.java:833)[optimized]
>     at java/util/WeakHashMap.eq(WeakHashMap.java:254)[inlined]
>     at java/util/WeakHashMap.get(WeakHashMap.java:345)[optimized]
>     at org/apache/commons/beanutils/MethodUtils.getMatchingAccessibleMethod(MethodUtils.java:530)[optimized]
>     at org/apache/commons/beanutils/MethodUtils.invokeMethod(MethodUtils.java:209)[inlined]

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Resolved: (BEANUTILS-373) CLONE - MethodUtils is not thread safe because WeakFastHashMap which uses WeakHashMap is not thread-safe.

Posted by "Niall Pemberton (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/BEANUTILS-373?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Niall Pemberton resolved BEANUTILS-373.
---------------------------------------

       Resolution: Fixed
    Fix Version/s: 1.8.3

Doh! Must have had a brain fart when I applied the fix for BEANUTILS-318.

Thanks, this is now fixed:

http://svn.apache.org/viewvc?rev=926112&view=rev

> CLONE - MethodUtils is not thread safe because WeakFastHashMap which uses WeakHashMap is not thread-safe.
> ---------------------------------------------------------------------------------------------------------
>
>                 Key: BEANUTILS-373
>                 URL: https://issues.apache.org/jira/browse/BEANUTILS-373
>             Project: Commons BeanUtils
>          Issue Type: Bug
>          Components: Bean / Property Utils
>    Affects Versions: 1.8.2
>         Environment: Weblogic 9.2 on Linux, but should not be relevant
>            Reporter: Andrew Sunde
>            Assignee: Niall Pemberton
>             Fix For: 1.8.3
>
>
> The problem lies in the class org.apache.commons.beanutils.MethodUtils. This class is keeping a global cache in a non synchronized WeakFastHashMap (which claims to be syncronized). When operating in Fast mode (which is what the WeakFastHashMap is set to after it is created), it then access the underlining WeakHashMap without synchronization. Therefore this can lead to a corruption in the underlining HashMap.
> See the description of the WeakHashMap javadoc:
> From Java Sun: "
> Like most collection classes, this class is not synchronized. A synchronized WeakHashMap may be constructed using the Collections.synchronizedMap  method. 
> ....
> The behavior of the WeakHashMap class depends in part upon the actions of the garbage collector, so several familiar (though not required) Map invariants do not hold for this class. Because the garbage collector may discard keys at any time, a WeakHashMap may behave as though an unknown thread is silently removing entries.
> "
> Therefore even if you are doing a "get" from the hashmap, there is a chance that you could get a corrupted hashmap because the garbage collector could be changing the hashmap on the fly. This could lead to threads getting stuck in an infinite loop.
> The modification to make the MethodUtils cache thread safe is a one line change. 
> Before: 
> private static WeakFastHashMap cache = new WeakFastHashMap();
> After: 
> private static Map cache = Collections.synchronizedMap(new WeakHashMap());

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.