[ 
https://issues.apache.org/jira/browse/AXIOM-390?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Andreas Veithen resolved AXIOM-390.
-----------------------------------

    Resolution: Invalid

The leak reported by Tomcat is a false positive. The original implementation of 
the UIDGenerator indeed caused a class loader leak, but that has been fixed in 
1.2.12 (see AXIOM-354).

A thread local only causes a class loader leak if certain conditions are met, 
as described in [1]. However, condition 2 is not met here because the value of 
the thread local is of type long[]. Unfortunately, Tomcat is not able to check 
that condition and reports a false positive.

[1] http://code.google.com/p/arit/wiki/ThreadLocal

> Memory leak in UIDGenerator
> ---------------------------
>
>                 Key: AXIOM-390
>                 URL: https://issues.apache.org/jira/browse/AXIOM-390
>             Project: Axiom
>          Issue Type: Bug
>          Components: API
>    Affects Versions: 1.2.12
>         Environment: Tomcat 7.0.21, Axis2 1.6.1 with Axiom 1.2.12
>            Reporter: Detlef Günther
>
> Shutting down tomcat produces a list of error messages for each request of a 
> web service:
> 16.09.2011 08:36:16 org.apache.catalina.loader.WebappClassLoader 
> checkThreadLocalMapForLeaks
> SCHWERWIEGEND: The web application [/datatransfer] created a ThreadLocal with 
> key of type [org.apache.axiom.util.UIDGenerator$1] (value 
> [org.apache.axiom.util.UIDGenerator$1@252a78ee]) and a value of type [long[]] 
> (value [[J@7696452]) but failed to remove it when the web application was 
> stopped. Threads are going to be renewed over time to try and avoid a 
> probable memory leak. 
> Problem seems to be ThreadLocal, which cannot bee cleaned up after processing 
> the request. Eliminating ThreadLocal solves the problem:
> public final class UIDGenerator {
>       //      private static final long                               
> startTimeXorOperand;
>       private static final long                               
> threadIdXorOperand;
>       private static final long                               seqXorOperand;
>       static {
>               Random rand = new Random();
>               threadIdXorOperand = rand.nextLong();
>               //              startTimeXorOperand = rand.nextLong();
>               seqXorOperand = rand.nextLong();
>       }
>       private final static AtomicLong seqValue        = new AtomicLong(0);
>       private UIDGenerator() {
>       }
>       private static void writeReverseLongHex(long value, StringBuilder 
> buffer) {
>               for (int i = 0; i < 64; i += 4) {
>                       int n = (int) (value >> i) & 0xF;
>                       buffer.append((char) (n < 10 ? '0' + n : 'a' + n - 10));
>               }
>       }
>       /**
>        * Generate a unique ID as hex value and add it to the given buffer. 
> Note that
>        * with respect to the triplet, the order of nibbles is reversed, i.e. 
> the
>        * least significant nibble of the sequence is written first. This makes
>        * comparing two IDs for equality more efficient.
>        * 
>        * @param buffer
>        */
>       private static void generateHex(StringBuilder buffer) {
>               writeReverseLongHex(seqValue.incrementAndGet() ^ seqXorOperand, 
> buffer);
>               writeReverseLongHex(Thread.currentThread().getId() ^ 
> threadIdXorOperand,
>                               buffer);
>       }
> ...
>  

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira



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

Reply via email to