users@jaxb.java.net

Re: Unmarshalling race condition - appears fixed in 2.2.3u1

From: Pavel Bucek <pavel.bucek_at_oracle.com>
Date: Fri, 25 Mar 2011 22:34:55 +0100

Hello James,

looks like you were hitting this one: http://java.net/jira/browse/JAXB-596

patch:

$ svn diff -r 3370:3371
Index:
runtime/src/com/sun/xml/bind/v2/runtime/property/SingleMapNodeProperty.java
===================================================================
---
runtime/src/com/sun/xml/bind/v2/runtime/property/SingleMapNodeProperty.java
(revision 3370)
+++
runtime/src/com/sun/xml/bind/v2/runtime/property/SingleMapNodeProperty.java
(revision 3371)
@@ -155,20 +155,20 @@
       */
      private final Loader itemsLoader = new Loader(false) {

- private BeanT target;
- private ValueT map;
+ private ThreadLocal<BeanT> target = new ThreadLocal<BeanT>();
+ private ThreadLocal<ValueT> map = new ThreadLocal<ValueT>();

          @Override
          public void startElement(UnmarshallingContext.State state,
TagName ea) throws SAXException {
              // create or obtain the Map object
              try {
- target = (BeanT)state.prev.target;
- map = acc.get(target);
- if(map==null) {
- map = ClassFactory.create(mapImplClass);
+ target.set((BeanT)state.prev.target);
+ map.set(acc.get(target.get()));
+ if(map.get() == null) {
+ map.set(ClassFactory.create(mapImplClass));
                  }
- map.clear();
- state.target = map;
+ map.get().clear();
+ state.target = map.get();
              } catch (AccessorException e) {
                  // recover from error by setting a dummy Map that
receives and discards the values
                  handleGenericException(e,true);
@@ -180,7 +180,7 @@
          public void leaveElement(State state, TagName ea) throws
SAXException {
              super.leaveElement(state, ea);
              try {
- acc.set(target, map);
+ acc.set(target.get(), map.get());
              } catch (AccessorException ex) {
                  handleGenericException(ex,true);
              }


Regards,
Pavel

On 3/25/11 9:36 PM, James Cooper wrote:
> Hi,
>
> This week we discovered that one of our CXF based web services was
> behaving strangely under moderate load. We traced this down to a race
> condition in JAXB that sometimes caused unmarshalled objects returned
> by UnmarshallerImpl to be only partially populated. In our case we
> had something like this:
>
> public class Foo {
>
> private String name;
> private Map<String, String> properties;
>
> // standard getters / setters for both
> }
>
> Thread-1 calls unmarshal(), which creats Foo-Ref-A
> Thread-2 calls unmarshal(), which creats Foo-Ref-B
> Thread-1 would call Foo-Ref-A.setName()
> **Thread-1 would call Foo-Ref-B.setProperties() (with the data on the
> reader from Thread-2)
> Thread-2 would call Foo-Ref-B.setName()
> Thread-2 would call Foo-Ref-B.setProperties()
> Thread-1 would receive Foo-Ref-A
> Thread-2 would receive Foo-Ref-B
>
> So Foo-Ref-A would be processed by the web service, and bad things
> would happen because its properties had never been unmarshalled.
>
> We could confirm this problem in JAXB 2.2.1.1 (which ships with CXF
> 2.3.3). Dropping in JAXB 2.2.3u1 appears to have fixed the issue. We
> also observed that a brute-force synchronized lock in CXF (which we
> patched and rebuilt) that globally synchronized JAXB unmarshalling
> fixed the issue too. Obviously the latter is not something we would
> consider deploying, but it did help us isolate the area of the fault.
>
> We looked through the JAXB JIRA database, but didn't see any tickets
> that looked relevant.
>
> We're curious if anyone on the list knows if any threading/concurrency
> bugs were fixed in the June 2010 - January 2011 time range.
>
> thank you
>
> -- James
>
> --
>
> James Cooper
> Principal Consultant - Bitmechanic LLC
> http://www.bitmechanic.com/