You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomee.apache.org by "Howard W. Smith, Jr." <sm...@gmail.com> on 2013/03/29 20:13:39 UTC

Re: WebappClassLoader checkThreadLocalMapForLeaks finding leaks related to Google Apps API

Wow, someone responded to google-gson issue # 402[1]: Memory Leak in web
application; comment # 25, and shared the following, and this works in my
web app!

import com.google.gson.Gson;
import java.lang.ref.WeakReference;
import java.lang.reflect.Array;
import java.lang.reflect.Field;

class GSONThreadLocalImmolater {

        public static void main(final String[] args) {
                new Gson().toJson("blah");
                immolate(); // should print 1
        }

        static void immolate() {
                try {
                        int count = 0;
                        final Field threadLocalsField = Thread.class.
getDeclaredField("threadLocals");
                        threadLocalsField.setAccessible(true);
                        final Field inheritableThreadLocalsField = Thread.
class.getDeclaredField("inheritableThreadLocals");
                        inheritableThreadLocalsField.setAccessible(true);
                        for (final Thread thread : Thread.getAllStackTraces
().keySet()) {
                                count += clear(threadLocalsField.get(thread
));
                                count += clear(inheritableThreadLocalsField.
get(thread));
                        }
                        System.out.println("immolated " + count + " GSON
values in ThreadLocals");
                } catch (final Exception e) {
                        throw new Error("die", e);
                }
        }

        private static int clear(final Object threadLocalMap) throws
Exception {
                if (threadLocalMap == null)
                        return 0;
                int count = 0;
                final Field tableField = threadLocalMap.getClass().
getDeclaredField("table");
                tableField.setAccessible(true);
                final Object table = tableField.get(threadLocalMap);
                for (int i = 0, length = Array.getLength(table); i < length;
++i) {
                        final Object entry = Array.get(table, i);
                        if (entry != null) {
                                final Object threadLocal = ((WeakReference)
entry).get();
                                if (threadLocal != null && threadLocal.
getClass().getEnclosingClass() == Gson.class) {
                                        Array.set(table, i, null);
                                        ++count;
                                }
                        }
                }
                return count;
        }
}


[1] https://code.google.com/p/google-gson/issues/detail?id=402


On Tue, Dec 11, 2012 at 12:00 AM, Howard W. Smith, Jr. <
smithh032772@gmail.com> wrote:

> Please see exceptions below that usually occur when I shutdown TomEE (to
> deploy/drop a new WAR file). I am already using @PreDestroy on CDI
> @ApplicationScoped beanto stop other services. I think these exceptions are
> telling me that it might be best for me to do some type of stop-or-destroy
> Google Apss API as well.  Please confirm. Thanks.
>
>
> SEVERE: The web application [/mcmsweb] appears to have started a thread
> named [Thread-59] but has failed to stop it. This is very likely to create
> a memory leak.
> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
> clearReferencesThreads
> SEVERE: The web application [/mcmsweb] appears to have started a thread
> named [AWT-Windows] but has failed to stop it. This is very likely to
> create a memory leak.
> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
> checkThreadLocalMapForLeaks
> SEVERE: The web application [/mcmsweb] created a ThreadLocal with key of
> type [com.google.api.client.util.escape.Platform$1] (value
> [com.google.api.client.util.escape.Platform$1@1757c6b]) and a value of
> type [char[]] (value [[C@3b9319]) 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.
> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
> checkThreadLocalMapForLeaks
> SEVERE: The web application [/mcmsweb] created a ThreadLocal with key of
> type [com.google.api.client.util.escape.Platform$1] (value
> [com.google.api.client.util.escape.Platform$1@1757c6b]) and a value of
> type [char[]] (value [[C@13656a2]) 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.
> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
> checkThreadLocalMapForLeaks
> SEVERE: The web application [/mcmsweb] created a ThreadLocal with key of
> type [com.google.api.client.util.escape.Platform$1] (value
> [com.google.api.client.util.escape.Platform$1@1757c6b]) and a value of
> type [char[]] (value [[C@71c1ff]) 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.
> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
> checkThreadLocalMapForLeaks
> SEVERE: The web application [/mcmsweb] created a ThreadLocal with key of
> type [com.google.api.client.util.escape.Platform$1] (value
> [com.google.api.client.util.escape.Platform$1@1757c6b]) and a value of
> type [char[]] (value [[C@77759b]) 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.
> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
> checkThreadLocalMapForLeaks
> SEVERE: The web application [/mcmsweb] created a ThreadLocal with key of
> type [com.google.gson.Gson$1] (value [com.google.gson.Gson$1@ca428a]) and
> a value of type [java.util.HashMap] (value [{}]) 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.
> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
> checkThreadLocalMapForLeaks
> SEVERE: The web application [/mcmsweb] created a ThreadLocal with key of
> type [com.google.api.client.util.escape.Platform$1] (value
> [com.google.api.client.util.escape.Platform$1@1757c6b]) and a value of
> type [char[]] (value [[C@d685eb]) 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.
> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
> checkThreadLocalMapForLeaks
> SEVERE: The web application [/mcmsweb] created a ThreadLocal with key of
> type [com.google.api.client.util.escape.Platform$1] (value
> [com.google.api.client.util.escape.Platform$1@1757c6b]) and a value of
> type [char[]] (value [[C@1f21c3f]) 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.
> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
> checkThreadLocalMapForLeaks
> SEVERE: The web application [/mcmsweb] created a ThreadLocal with key of
> type [com.google.api.client.util.escape.Platform$1] (value
> [com.google.api.client.util.escape.Platform$1@1757c6b]) and a value of
> type [char[]] (value [[C@1c7a6e]) 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.
>
>

Re: WebappClassLoader checkThreadLocalMapForLeaks finding leaks related to Google Apps API

Posted by "Howard W. Smith, Jr." <sm...@gmail.com>.
I tweaked it for my web app and defined the class as follows, and I call in
my @PreDestroy method of my 'only' CDI @ApplicationScoped bean.

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pf;

import com.google.gson.Gson;

import java.lang.ref.WeakReference;
import java.lang.reflect.Array;
import java.lang.reflect.Field;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Administrator
 *
 * google-gson issue # 402: Memory Leak in web application; comment # 25
 * https://code.google.com/p/google-gson/issues/detail?id=402
 */
public class GSONThreadLocalImmolater {

    final Logger logger =
LoggerFactory.getLogger(GSONThreadLocalImmolater.class);

    Boolean debug;

    public GSONThreadLocalImmolater() {
        debug = true;
    }

    public Integer immolate() {
        int count = 0;
        try {
            final Field threadLocalsField =
Thread.class.getDeclaredField("threadLocals");
            threadLocalsField.setAccessible(true);
            final Field inheritableThreadLocalsField =
Thread.class.getDeclaredField("inheritableThreadLocals");
            inheritableThreadLocalsField.setAccessible(true);
            for (final Thread thread : Thread.getAllStackTraces().keySet())
{
                    count += clear(threadLocalsField.get(thread));
                    count +=
clear(inheritableThreadLocalsField.get(thread));
            }
            logger.info("immolated " + count + " GSON values in
ThreadLocals");
        } catch (Exception e) {
            throw new Error("GSONThreadLocalImmolater.immolate()", e);
        }
        return count;
    }

    private int clear(final Object threadLocalMap) throws Exception {
        if (threadLocalMap == null)
                return 0;
        int count = 0;
        final Field tableField =
threadLocalMap.getClass().getDeclaredField("table");
        tableField.setAccessible(true);
        final Object table = tableField.get(threadLocalMap);
        for (int i = 0, length = Array.getLength(table); i < length; ++i) {
            final Object entry = Array.get(table, i);
            if (entry != null) {
                final Object threadLocal = ((WeakReference)entry).get();
                if (threadLocal != null &&
threadLocal.getClass().getEnclosingClass() == Gson.class) {
                    log(i, threadLocal);
                    Array.set(table, i, null);
                    ++count;
                }
                else if (threadLocal != null) {
                    log(i, threadLocal);
                    Array.set(table, i, null);
                }
            }
        }
        return count;
    }

    private void log(int i, final Object threadLocal) {
        if (!debug) {
            return;
        }
        if (threadLocal.getClass() != null &&
            threadLocal.getClass().getEnclosingClass() != null &&
            threadLocal.getClass().getEnclosingClass().getName() != null) {

            logger.info("threadLocalMap(" + i + "): " +

threadLocal.getClass().getEnclosingClass().getName());
        }
        else if (threadLocal.getClass() != null &&
                 threadLocal.getClass().getName() != null) {
            logger.info("threadLocalMap(" + i + "): " +
threadLocal.getClass().getName());
        }
        else {
            logger.info("threadLocalMap(" + i + "): cannot identify
threadlocal class name");
        }
    }

}



On Fri, Mar 29, 2013 at 3:13 PM, Howard W. Smith, Jr. <
smithh032772@gmail.com> wrote:

> Wow, someone responded to google-gson issue # 402[1]: Memory Leak in web
> application; comment # 25, and shared the following, and this works in my
> web app!
>
> import com.google.gson.Gson;
> import java.lang.ref.WeakReference;
> import java.lang.reflect.Array;
> import java.lang.reflect.Field;
>
> class GSONThreadLocalImmolater {
>
>         public static void main(final String[] args) {
>                 new Gson().toJson("blah");
>                 immolate(); // should print 1
>         }
>
>         static void immolate() {
>                 try {
>                         int count = 0;
>                         final Field threadLocalsField = Thread.class.
> getDeclaredField("threadLocals");
>                         threadLocalsField.setAccessible(true);
>                         final Field inheritableThreadLocalsField = Thread.
> class.getDeclaredField("inheritableThreadLocals");
>                         inheritableThreadLocalsField.setAccessible(true);
>                         for (final Thread thread : Thread.
> getAllStackTraces().keySet()) {
>                                 count += clear(threadLocalsField.get(
> thread));
>                                 count += clear(
> inheritableThreadLocalsField.get(thread));
>                         }
>                         System.out.println("immolated " + count + " GSON
> values in ThreadLocals");
>                 } catch (final Exception e) {
>                         throw new Error("die", e);
>                 }
>         }
>
>         private static int clear(final Object threadLocalMap) throws
> Exception {
>                 if (threadLocalMap == null)
>                         return 0;
>                 int count = 0;
>                 final Field tableField = threadLocalMap.getClass().
> getDeclaredField("table");
>                 tableField.setAccessible(true);
>                 final Object table = tableField.get(threadLocalMap);
>                 for (int i = 0, length = Array.getLength(table); i <length
> ; ++i) {
>                         final Object entry = Array.get(table, i);
>                         if (entry != null) {
>                                 final Object threadLocal = ((WeakReference
> )entry).get();
>                                 if (threadLocal != null && threadLocal.
> getClass().getEnclosingClass() == Gson.class) {
>                                         Array.set(table, i, null);
>                                         ++count;
>                                 }
>                         }
>                 }
>                 return count;
>         }
> }
>
>
> [1] https://code.google.com/p/google-gson/issues/detail?id=402
>
>
> On Tue, Dec 11, 2012 at 12:00 AM, Howard W. Smith, Jr. <
> smithh032772@gmail.com> wrote:
>
>> Please see exceptions below that usually occur when I shutdown TomEE (to
>> deploy/drop a new WAR file). I am already using @PreDestroy on CDI
>> @ApplicationScoped beanto stop other services. I think these exceptions are
>> telling me that it might be best for me to do some type of stop-or-destroy
>> Google Apss API as well.  Please confirm. Thanks.
>>
>>
>> SEVERE: The web application [/mcmsweb] appears to have started a thread
>> named [Thread-59] but has failed to stop it. This is very likely to create
>> a memory leak.
>> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
>> clearReferencesThreads
>> SEVERE: The web application [/mcmsweb] appears to have started a thread
>> named [AWT-Windows] but has failed to stop it. This is very likely to
>> create a memory leak.
>> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
>> checkThreadLocalMapForLeaks
>> SEVERE: The web application [/mcmsweb] created a ThreadLocal with key of
>> type [com.google.api.client.util.escape.Platform$1] (value
>> [com.google.api.client.util.escape.Platform$1@1757c6b]) and a value of
>> type [char[]] (value [[C@3b9319]) 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.
>> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
>> checkThreadLocalMapForLeaks
>> SEVERE: The web application [/mcmsweb] created a ThreadLocal with key of
>> type [com.google.api.client.util.escape.Platform$1] (value
>> [com.google.api.client.util.escape.Platform$1@1757c6b]) and a value of
>> type [char[]] (value [[C@13656a2]) 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.
>> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
>> checkThreadLocalMapForLeaks
>> SEVERE: The web application [/mcmsweb] created a ThreadLocal with key of
>> type [com.google.api.client.util.escape.Platform$1] (value
>> [com.google.api.client.util.escape.Platform$1@1757c6b]) and a value of
>> type [char[]] (value [[C@71c1ff]) 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.
>> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
>> checkThreadLocalMapForLeaks
>> SEVERE: The web application [/mcmsweb] created a ThreadLocal with key of
>> type [com.google.api.client.util.escape.Platform$1] (value
>> [com.google.api.client.util.escape.Platform$1@1757c6b]) and a value of
>> type [char[]] (value [[C@77759b]) 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.
>> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
>> checkThreadLocalMapForLeaks
>> SEVERE: The web application [/mcmsweb] created a ThreadLocal with key of
>> type [com.google.gson.Gson$1] (value [com.google.gson.Gson$1@ca428a])
>> and a value of type [java.util.HashMap] (value [{}]) 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.
>> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
>> checkThreadLocalMapForLeaks
>> SEVERE: The web application [/mcmsweb] created a ThreadLocal with key of
>> type [com.google.api.client.util.escape.Platform$1] (value
>> [com.google.api.client.util.escape.Platform$1@1757c6b]) and a value of
>> type [char[]] (value [[C@d685eb]) 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.
>> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
>> checkThreadLocalMapForLeaks
>> SEVERE: The web application [/mcmsweb] created a ThreadLocal with key of
>> type [com.google.api.client.util.escape.Platform$1] (value
>> [com.google.api.client.util.escape.Platform$1@1757c6b]) and a value of
>> type [char[]] (value [[C@1f21c3f]) 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.
>> Dec 10, 2012 11:16:12 PM org.apache.catalina.loader.WebappClassLoader
>> checkThreadLocalMapForLeaks
>> SEVERE: The web application [/mcmsweb] created a ThreadLocal with key of
>> type [com.google.api.client.util.escape.Platform$1] (value
>> [com.google.api.client.util.escape.Platform$1@1757c6b]) and a value of
>> type [char[]] (value [[C@1c7a6e]) 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.
>>
>>
>