FinalizableReferenceQueue still leaks #288

Open
gissuebot opened this Issue Jul 7, 2014 · 100 comments

Comments

Projects
None yet
1 participant
@gissuebot

From gili.tzabari on December 25, 2008 12:51:41

Issue 227 is closed but the problem was not really fixed.

Stuart's comment #8 explains what remains to be fixed: https://code.google.com/p/google-guice/issues/detail?id=227&can=1&start=200#c8

Original issue: http://code.google.com/p/google-guice/issues/detail?id=288

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From limpbizkit on December 30, 2008 14:03:08

I've started working on a fix, but it might not be worthwhile... http://groups.google.com/group/google-guice-dev/browse_thread/thread/28caab16fc75ad25

From limpbizkit on December 30, 2008 14:03:08

I've started working on a fix, but it might not be worthwhile... http://groups.google.com/group/google-guice-dev/browse_thread/thread/28caab16fc75ad25

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From limpbizkit on December 30, 2008 15:39:59

(No comment was entered for this change.)

Labels: Priority-High Milestone-Release2.0

From limpbizkit on December 30, 2008 15:39:59

(No comment was entered for this change.)

Labels: Priority-High Milestone-Release2.0

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From gili.tzabari on December 30, 2008 16:10:12

  1. Is there a way to use SoftReferences without a dedicated thread (perhaps similar
    to how WeakHashMap works)?
  2. Another possibility (one that has been brought up before) is exposing an explicit
    method for shutting down the Thread. Developers would invoke this method from
    ServletContextListener.contextDestroyed()

From gili.tzabari on December 30, 2008 16:10:12

  1. Is there a way to use SoftReferences without a dedicated thread (perhaps similar
    to how WeakHashMap works)?
  2. Another possibility (one that has been brought up before) is exposing an explicit
    method for shutting down the Thread. Developers would invoke this method from
    ServletContextListener.contextDestroyed()
@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From limpbizkit on December 30, 2008 21:03:52

  1. yes
  2. not necessary. The thread improved speed and memory usage by vacuuming out the collected elements. But
    it's not strictly necessary.

From limpbizkit on December 30, 2008 21:03:52

  1. yes
  2. not necessary. The thread improved speed and memory usage by vacuuming out the collected elements. But
    it's not strictly necessary.
@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on December 31, 2008 14:19:55

Any thoughts on the experimental concurrent reference map from JSR166? http://viewvc.jboss.org/cgi- bin/viewvc.cgi/jbosscache/experimental/jsr166/src/jsr166y/ConcurrentReferenceHashMap.
java?view=markup

it doesn't use a thread, but still supports the concurrent map API.

From mcculls on December 31, 2008 14:19:55

Any thoughts on the experimental concurrent reference map from JSR166? http://viewvc.jboss.org/cgi- bin/viewvc.cgi/jbosscache/experimental/jsr166/src/jsr166y/ConcurrentReferenceHashMap.
java?view=markup

it doesn't use a thread, but still supports the concurrent map API.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From gili.tzabari on December 31, 2008 14:32:44

Very cool! Doug Lea wrote the thing so I am willing to bet that it's pretty solid ;)
There is also the fact that it's scheduled for inclusion in Java7.

From gili.tzabari on December 31, 2008 14:32:44

Very cool! Doug Lea wrote the thing so I am willing to bet that it's pretty solid ;)
There is also the fact that it's scheduled for inclusion in Java7.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From limpbizkit on December 31, 2008 15:42:52

Unfortunately, although it's extremely handy, Doug Lea's ConcurrentReferenceHashMap doesn't have the one
method we need, whose signature would resemble either this
  public void putIfAbsent(K key, Function<K, V> keyToValue)
or perhaps this (which is what ReferenceCache uses):
  public abstract V create(K)

From limpbizkit on December 31, 2008 15:42:52

Unfortunately, although it's extremely handy, Doug Lea's ConcurrentReferenceHashMap doesn't have the one
method we need, whose signature would resemble either this
  public void putIfAbsent(K key, Function<K, V> keyToValue)
or perhaps this (which is what ReferenceCache uses):
  public abstract V create(K)

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From gili.tzabari on December 31, 2008 16:13:22

Jesse,

I suppose you could always file a RFE with Doug and see what he says. Alternatively,
would it be possible to store Function in place of the actual value?

From gili.tzabari on December 31, 2008 16:13:22

Jesse,

I suppose you could always file a RFE with Doug and see what he says. Alternatively,
would it be possible to store Function in place of the actual value?

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From dhanji on January 03, 2009 22:45:32

I wanted to add that awesome method to CHM itself, but there didn't seem to be much enthusiasm when I tried.

Afaik it is not solely Doug Lea's RefMap, it was developed by Red Hat et al., in parallel to a somewhat better
implementation that Google open sourced (viz. ReferenceCache). Unfortunately for us, the wrong one made it
into the JDK =(

From dhanji on January 03, 2009 22:45:32

I wanted to add that awesome method to CHM itself, but there didn't seem to be much enthusiasm when I tried.

Afaik it is not solely Doug Lea's RefMap, it was developed by Red Hat et al., in parallel to a somewhat better
implementation that Google open sourced (viz. ReferenceCache). Unfortunately for us, the wrong one made it
into the JDK =(

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From gili.tzabari on January 03, 2009 22:50:35

I didn't get the impression that it was too late to make changes to their
implementation. Did you file a formal RFE with them regarding this issue (do they
even have a public bug tracking system)? If so please link to it so I can run it by
my contacts at Sun. There is always room to apply more pressure :)

From gili.tzabari on January 03, 2009 22:50:35

I didn't get the impression that it was too late to make changes to their
implementation. Did you file a formal RFE with them regarding this issue (do they
even have a public bug tracking system)? If so please link to it so I can run it by
my contacts at Sun. There is always room to apply more pressure :)

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From crazyboblee on January 04, 2009 10:19:58

Nothing has made it into the JDK. Doug hasn't even actually looked at the RedHat impl (which doesn't actually
work). I already sent Doug a much better impl that shares code w/ CHM.

From crazyboblee on January 04, 2009 10:19:58

Nothing has made it into the JDK. Doug hasn't even actually looked at the RedHat impl (which doesn't actually
work). I already sent Doug a much better impl that shares code w/ CHM.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From dmdabbs on March 16, 2009 09:57:43

// Comment 11 by crazyboblee, Jan 04, 2009
// Nothing has made it into the JDK. Doug hasn't even actually looked at the RedHat
impl (which doesn't actually
//work). I already sent Doug a much better impl that shares code w/ CHM.

Is this better impl available anywhere?

From dmdabbs on March 16, 2009 09:57:43

// Comment 11 by crazyboblee, Jan 04, 2009
// Nothing has made it into the JDK. Doug hasn't even actually looked at the RedHat
impl (which doesn't actually
//work). I already sent Doug a much better impl that shares code w/ CHM.

Is this better impl available anywhere?

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From crazyboblee on March 16, 2009 10:03:53

Yes. Check out MapMaker in Google Collections
( https://code.google.com/p/google-collections/ ).

From crazyboblee on March 16, 2009 10:03:53

Yes. Check out MapMaker in Google Collections
( https://code.google.com/p/google-collections/ ).

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From limpbizkit on May 03, 2009 15:49:41

I believe this should be fixed. At a minimum, we now respect a security manager that refuses to let us spawn
threads.

Status: Fixed

From limpbizkit on May 03, 2009 15:49:41

I believe this should be fixed. At a minimum, we now respect a security manager that refuses to let us spawn
threads.

Status: Fixed

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From syvalta@yahoo.com on October 06, 2009 07:32:52

It seems to me that this issue is not fixed. From
com.google.inject.internal.Finalizer there is still the context class loader
reference, which has been discussed in the related issues.

From syvalta@yahoo.com on October 06, 2009 07:32:52

It seems to me that this issue is not fixed. From
com.google.inject.internal.Finalizer there is still the context class loader
reference, which has been discussed in the related issues.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From crazyboblee on October 06, 2009 07:42:41

Yeah, it still needs some work if you don't want to use a SM. I'm on it.

Status: Accepted

From crazyboblee on October 06, 2009 07:42:41

Yeah, it still needs some work if you don't want to use a SM. I'm on it.

Status: Accepted

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From alen_vrecko@yahoo.com on May 02, 2010 10:14:28

How about a refacture? MapMaker, that causes the thread and subsequently memory leak,
is used only at 2 places.

o) StackTraceElements. This can be refactured so it doesn't use weak-soft map. I just
removed the map entirely. Alternatively the caller could supply a plain HashMap and
clear it at the end when using StactTraceElements/Errors.

o) BytecodeGen. This is a bit trickier. I just disabled the caching of
BridgeClassloader. Imho, a reasonable compromise is if you disable bridge classloader
then the weak-weak map is not started as no bridge class loaders will be cached.

Alternatively instead of static cache with MapMaker, how about per Injector instance
cache with just plain HashMap?

Attachment: gist
   redeploySafe.diff

From alen_vrecko@yahoo.com on May 02, 2010 10:14:28

How about a refacture? MapMaker, that causes the thread and subsequently memory leak,
is used only at 2 places.

o) StackTraceElements. This can be refactured so it doesn't use weak-soft map. I just
removed the map entirely. Alternatively the caller could supply a plain HashMap and
clear it at the end when using StactTraceElements/Errors.

o) BytecodeGen. This is a bit trickier. I just disabled the caching of
BridgeClassloader. Imho, a reasonable compromise is if you disable bridge classloader
then the weak-weak map is not started as no bridge class loaders will be cached.

Alternatively instead of static cache with MapMaker, how about per Injector instance
cache with just plain HashMap?

Attachment: gist
   redeploySafe.diff

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on May 02, 2010 18:11:52

Well there's a reason for both of these weak caches - namely that you don't want to
keep creating the same object again and again (because it's expensive) but you also
want to have them automatically cleaned up when they're not needed.

By removing these caches you'd ironically be increasing the memory (and CPU) used by
Guice. In addition by turning off the bridge classloader cache you would create way
more classloaders than necessary which could exhaust the PermGen space.

(BTW - the classloader bridging is potentially needed whenever you have custom
classloaders loading your classes... be it application servers, tomcat, or OSGi)

From mcculls on May 02, 2010 18:11:52

Well there's a reason for both of these weak caches - namely that you don't want to
keep creating the same object again and again (because it's expensive) but you also
want to have them automatically cleaned up when they're not needed.

By removing these caches you'd ironically be increasing the memory (and CPU) used by
Guice. In addition by turning off the bridge classloader cache you would create way
more classloaders than necessary which could exhaust the PermGen space.

(BTW - the classloader bridging is potentially needed whenever you have custom
classloaders loading your classes... be it application servers, tomcat, or OSGi)

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From alen_vrecko@yahoo.com on May 03, 2010 02:21:27

From my understanding (or lack thereof) your comment is spot on if you put Guice in
bootclasspath. There the weak caches and bridge CL really shine. I can see it.

Now I must be missing something obvious but I don't think the behaviour is the same
when you put the guice.jar in the WAR. All the Guice classes get loaded in WebAppCl
and all the generated classes get loaded in the WACL or be it BCL.

When you redeploy/uninstall everything is eligible for GC. How much more can you
bargain for? Here I am at a loss, I don't see how weak caches will help here. What am
I missing?

From alen_vrecko@yahoo.com on May 03, 2010 02:21:27

From my understanding (or lack thereof) your comment is spot on if you put Guice in
bootclasspath. There the weak caches and bridge CL really shine. I can see it.

Now I must be missing something obvious but I don't think the behaviour is the same
when you put the guice.jar in the WAR. All the Guice classes get loaded in WebAppCl
and all the generated classes get loaded in the WACL or be it BCL.

When you redeploy/uninstall everything is eligible for GC. How much more can you
bargain for? Here I am at a loss, I don't see how weak caches will help here. What am
I missing?

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on May 03, 2010 02:40:29

By removing the weak caches you're forcing it to create new objects every time - even
though it might have created the same object in the past. For each of these use-cases
creating the object is an expensive operation, hence the cache. The situation is even
worse with classloaders because by creating one-per-bridged-type you would be making
the situation worse by isolating each bridged-type in its own tiny classloader (which
break certain visibility rules and would be a big overhead).

Even with WAR files you can have custom classloaders (typically when you want to
share classes or resources). Removing this cache (and changing to default to disable
bridging) would break a lot of applications that rely on this feature.

IMHO bridging should still be enabled by default - of course the creation of the
cache could be put inside a static initializer and made optional depending on the
flag. Then you could simply set the property to avoid the bridge cache.

From mcculls on May 03, 2010 02:40:29

By removing the weak caches you're forcing it to create new objects every time - even
though it might have created the same object in the past. For each of these use-cases
creating the object is an expensive operation, hence the cache. The situation is even
worse with classloaders because by creating one-per-bridged-type you would be making
the situation worse by isolating each bridged-type in its own tiny classloader (which
break certain visibility rules and would be a big overhead).

Even with WAR files you can have custom classloaders (typically when you want to
share classes or resources). Removing this cache (and changing to default to disable
bridging) would break a lot of applications that rely on this feature.

IMHO bridging should still be enabled by default - of course the creation of the
cache could be put inside a static initializer and made optional depending on the
flag. Then you could simply set the property to avoid the bridge cache.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From jose.illescas on May 17, 2010 09:28:17

This feature must be in 2.1 roadmap?

Now tomcat (from 6.0.26 version) logout as a possible memory leak:

<SEVERE> <WebappClassLoader.clearReferencesThreads> A web application appears to have
started a thread named [com.google.inject.internal.Finalizer] but has failed to stop
it. This is very likely to create a memory leak.

<SEVERE> <WebappClassLoader.clearThreadLocalMap> A web application created a
ThreadLocal with key of type [null] (value [com.google.inject.InjectorImpl$1@f2f585])
and a value of type [java.lang.Object[]] (value [[Ljava.lang.Object;@15fdf31]) but
failed to remove it when the web application was stopped. To prevent a memory leak,
the ThreadLocal has been forcibly removed.

From jose.illescas on May 17, 2010 09:28:17

This feature must be in 2.1 roadmap?

Now tomcat (from 6.0.26 version) logout as a possible memory leak:

<SEVERE> <WebappClassLoader.clearReferencesThreads> A web application appears to have
started a thread named [com.google.inject.internal.Finalizer] but has failed to stop
it. This is very likely to create a memory leak.

<SEVERE> <WebappClassLoader.clearThreadLocalMap> A web application created a
ThreadLocal with key of type [null] (value [com.google.inject.InjectorImpl$1@f2f585])
and a value of type [java.lang.Object[]] (value [[Ljava.lang.Object;@15fdf31]) but
failed to remove it when the web application was stopped. To prevent a memory leak,
the ThreadLocal has been forcibly removed.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From sameb@google.com on May 17, 2010 14:30:22

Guava's is now using a new implementation of MapMaker that doesn't use the extra
thread..  can we use that?

From sameb@google.com on May 17, 2010 14:30:22

Guava's is now using a new implementation of MapMaker that doesn't use the extra
thread..  can we use that?

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From terciofilho on September 09, 2010 13:29:09

Any news? Any workaround?

From terciofilho on September 09, 2010 13:29:09

Any news? Any workaround?

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From alen_vrecko@yahoo.com on September 10, 2010 07:05:57

FWIW I am using a slightly changed version of Guice that doesn't leak on redeploy. See the svn patch (against tagged 2.0 release). Basically I just get rid of non-strong maps that cause the finalizer thread to start.

Changes made:

o) StackTraceElements originally uses weak.soft map(Thread). I've replaced this with a plain strong map which is cleared when Guice ends reporting errors.

o) BytecodeGen uses a weak.weak cache(Thread). I've put the cache in IODH (lazy singleton). I see that the latest code also follows a similar approach. Therefore if bridging is disabled the thread will not be started.

o) I've made bridging disabled by default as I don't see any added value for a plain servlet setup. It works also on WebSphere and don't see the point of making sure my co-workers diligently disable the bridging. Besides putting Guice in boot class path still produces a memory leak...

o) Replaced ThreadLocal with a plain concurrent map so Tomcat no longer spams with SEVERE ThreadLocal not cleared warning. It is less than 2x slower but this is acceptable price for me. I don't expect this to be popular choice.

I wouldn't be surprised if at Google they have a custom JDK that has this functionality built in.

Attachment: gist
   RedeplyForGuice.patch

From alen_vrecko@yahoo.com on September 10, 2010 07:05:57

FWIW I am using a slightly changed version of Guice that doesn't leak on redeploy. See the svn patch (against tagged 2.0 release). Basically I just get rid of non-strong maps that cause the finalizer thread to start.

Changes made:

o) StackTraceElements originally uses weak.soft map(Thread). I've replaced this with a plain strong map which is cleared when Guice ends reporting errors.

o) BytecodeGen uses a weak.weak cache(Thread). I've put the cache in IODH (lazy singleton). I see that the latest code also follows a similar approach. Therefore if bridging is disabled the thread will not be started.

o) I've made bridging disabled by default as I don't see any added value for a plain servlet setup. It works also on WebSphere and don't see the point of making sure my co-workers diligently disable the bridging. Besides putting Guice in boot class path still produces a memory leak...

o) Replaced ThreadLocal with a plain concurrent map so Tomcat no longer spams with SEVERE ThreadLocal not cleared warning. It is less than 2x slower but this is acceptable price for me. I don't expect this to be popular choice.

I wouldn't be surprised if at Google they have a custom JDK that has this functionality built in.

Attachment: gist
   RedeplyForGuice.patch

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From tj.rothwell on October 19, 2010 07:44:17

@crazyboblee Has this issue dropped to the floor? Is the SM method the only way to address this issue without custom patches? Looking forward to a status update. :)

From tj.rothwell on October 19, 2010 07:44:17

@crazyboblee Has this issue dropped to the floor? Is the SM method the only way to address this issue without custom patches? Looking forward to a status update. :)

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From miazzo.valentino on December 10, 2010 05:35:59

Wow, Guice 3.0 is RC1 and this bug is still open.
It will be fixed in Guice 3.0?

From miazzo.valentino on December 10, 2010 05:35:59

Wow, Guice 3.0 is RC1 and this bug is still open.
It will be fixed in Guice 3.0?

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From jose.illescas on December 10, 2010 07:07:02

You can add your comment (or opinion) on wiki page of 3.0 version ( https://code.google.com/p/google-guice/wiki/Guice30 )

From jose.illescas on December 10, 2010 07:07:02

You can add your comment (or opinion) on wiki page of 3.0 version ( https://code.google.com/p/google-guice/wiki/Guice30 )

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on January 11, 2011 15:57:16

Here's a potential solution, which adds a new property:

   -Dguice.executor.class

* This property can be used to pass a custom java.util.concurrent.Executor implementation class to Guice.

  • Setting it to the empty string (-Dguice.executor.class=) will disable the Guice Finalizer thread completely.
  • If this property is unset then Guice will use a simple Executor that creates a new thread (as at the moment).

This should avoid the main coupling issue wrt. who creates the actual thread (the Finalizer runnable is already decoupled) and also provide some means for shutting down the task from the outside without having to add a public shutdown API.

Note: I'm currently testing this patch in an experimental sisu-guice build: sonatype/sisu-guice@d5dc781

Attachment: gist
   GUICE_ISSUE_288_20110111.txt

From mcculls on January 11, 2011 15:57:16

Here's a potential solution, which adds a new property:

   -Dguice.executor.class

* This property can be used to pass a custom java.util.concurrent.Executor implementation class to Guice.

  • Setting it to the empty string (-Dguice.executor.class=) will disable the Guice Finalizer thread completely.
  • If this property is unset then Guice will use a simple Executor that creates a new thread (as at the moment).

This should avoid the main coupling issue wrt. who creates the actual thread (the Finalizer runnable is already decoupled) and also provide some means for shutting down the task from the outside without having to add a public shutdown API.

Note: I'm currently testing this patch in an experimental sisu-guice build: sonatype/sisu-guice@d5dc781

Attachment: gist
   GUICE_ISSUE_288_20110111.txt

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on January 11, 2011 16:42:31

Updated patch which avoids keeping a reference to the custom executor class.

Attachment: gist
   GUICE_ISSUE_288_20110112.txt

From mcculls on January 11, 2011 16:42:31

Updated patch which avoids keeping a reference to the custom executor class.

Attachment: gist
   GUICE_ISSUE_288_20110112.txt

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on January 17, 2011 05:44:23

Latest patch: use "-Dguice.executor.class=NONE" to disable the background thread, as this makes the intention clear. Decided against using "false" because that would suggest that "true" was a valid value - similarly using the word "null" could be confused with the value null. "NONE" seems a reasonable compromise.

Attachment: gist
   GUICE_ISSUE_288_20110117.patch

From mcculls on January 17, 2011 05:44:23

Latest patch: use "-Dguice.executor.class=NONE" to disable the background thread, as this makes the intention clear. Decided against using "false" because that would suggest that "true" was a valid value - similarly using the word "null" could be confused with the value null. "NONE" seems a reasonable compromise.

Attachment: gist
   GUICE_ISSUE_288_20110117.patch

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From cowwoc%bbs.darktech.org@gtempaccount.com on January 17, 2011 06:20:48

So if I understand you correctly: the benefit of allowing users to configure a custom Executor is that they can then invoke ExecutorService.shutdown(). Is that correct?

From cowwoc%bbs.darktech.org@gtempaccount.com on January 17, 2011 06:20:48

So if I understand you correctly: the benefit of allowing users to configure a custom Executor is that they can then invoke ExecutorService.shutdown(). Is that correct?

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on January 17, 2011 06:32:37

There are many benefits:

  1. the container can decide not to accept the task, in which case the cleanup work is only done in the foreground

  2. the container can run the task on a 'pure' thread with no references to the app - part of the problem at the moment is that Guice/Guava creates a child thread which can have internal references back to the parent thread (and from the to the app domain) that then lead to it not being GC'd properly - this should mean the thread will shutdown itself cleaning when the app is undeployed

  3. the container can decide to attempt to stop the work by interrupting the runnable with an exception/error or if that fails by forcibly stopping the thread as a last resort

So while the Executor approach will let you forcibly shut down the thread, it should be seen as a last resort.

From mcculls on January 17, 2011 06:32:37

There are many benefits:

  1. the container can decide not to accept the task, in which case the cleanup work is only done in the foreground

  2. the container can run the task on a 'pure' thread with no references to the app - part of the problem at the moment is that Guice/Guava creates a child thread which can have internal references back to the parent thread (and from the to the app domain) that then lead to it not being GC'd properly - this should mean the thread will shutdown itself cleaning when the app is undeployed

  3. the container can decide to attempt to stop the work by interrupting the runnable with an exception/error or if that fails by forcibly stopping the thread as a last resort

So while the Executor approach will let you forcibly shut down the thread, it should be seen as a last resort.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From maxb@j.maxb.eu on January 17, 2011 07:16:26

Is controlling this by means of a system property a good idea? Surely the sorts of embedded environments where you would want to avoid this behaviour are ones where you may not conveniently be able to add system properties?

From maxb@j.maxb.eu on January 17, 2011 07:16:26

Is controlling this by means of a system property a good idea? Surely the sorts of embedded environments where you would want to avoid this behaviour are ones where you may not conveniently be able to add system properties?

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on January 17, 2011 07:30:07

Using a system property allows people to experiment with this feature before committing to a particular API. Remember this is only a proposal at the moment (although available for testing over at sisu-guice on github).

From mcculls on January 17, 2011 07:30:07

Using a system property allows people to experiment with this feature before committing to a particular API. Remember this is only a proposal at the moment (although available for testing over at sisu-guice on github).

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From cowwoc%bbs.darktech.org@gtempaccount.com on January 17, 2011 07:54:45

Moved comment from https://code.google.com/p/guava-libraries/issues/detail?id=92#c38 -----
Let's remember: the main goal of this RFE is to solve a pain-point for web applications, not desktop applications.

There is no ambiguity for webapps as to who should invoke the shutdown() method because there are well-defined shutdown hooks and expectations for what should happen on subsequent requests.

System properties are a bad fit for webapps as they cannot be controlled on a per-webapp basis.

Don't get me wrong. I think your use of Executors is quite clever. I just don't think it really solves this RFE.

Here's an idea: how about allowing us to configure the Executor in the Guice Module? For example:

public class MyModule extends AbstractModule {
   private final ExecutorService sharedExecutor = ...;

   protected void configure() {
     bindConstant().annotatedWith(GuiceExecutorAnnotation).to(sharedExecutor);
   }
 }

Nothing prevents you from sharing the same executor across all injectors, and if you really want separate Executors you could do that as well.

From cowwoc%bbs.darktech.org@gtempaccount.com on January 17, 2011 07:54:45

Moved comment from https://code.google.com/p/guava-libraries/issues/detail?id=92#c38 -----
Let's remember: the main goal of this RFE is to solve a pain-point for web applications, not desktop applications.

There is no ambiguity for webapps as to who should invoke the shutdown() method because there are well-defined shutdown hooks and expectations for what should happen on subsequent requests.

System properties are a bad fit for webapps as they cannot be controlled on a per-webapp basis.

Don't get me wrong. I think your use of Executors is quite clever. I just don't think it really solves this RFE.

Here's an idea: how about allowing us to configure the Executor in the Guice Module? For example:

public class MyModule extends AbstractModule {
   private final ExecutorService sharedExecutor = ...;

   protected void configure() {
     bindConstant().annotatedWith(GuiceExecutorAnnotation).to(sharedExecutor);
   }
 }

Nothing prevents you from sharing the same executor across all injectors, and if you really want separate Executors you could do that as well.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on January 17, 2011 08:11:06

Unfortunately that's not possible - all this happens before the injector is created, in code that has no knowledge of individual injectors or their bindings. The only alternative I can think of would be a static method somewhere - but that would have to be accepted by other member of the Guice team.

For now the patch uses a system property because it's still only a proposal - what would help is if people tried out the snapshot that contains this experimental patch to see if it resolved the unload/shutdown issue for them: https://repository.sonatype.org/content/groups/forge/org/sonatype/sisu/sisu-guice/3.0-SNAPSHOT/ The system property shouldn't be a problem when it comes to testing the feature on a development machine.

Positive feedback would help towards getting this patch applied - then hopefully we could move on to discuss how best to configure this setting (be it a static method or another approach). Alternative patches would also welcome.

From mcculls on January 17, 2011 08:11:06

Unfortunately that's not possible - all this happens before the injector is created, in code that has no knowledge of individual injectors or their bindings. The only alternative I can think of would be a static method somewhere - but that would have to be accepted by other member of the Guice team.

For now the patch uses a system property because it's still only a proposal - what would help is if people tried out the snapshot that contains this experimental patch to see if it resolved the unload/shutdown issue for them: https://repository.sonatype.org/content/groups/forge/org/sonatype/sisu/sisu-guice/3.0-SNAPSHOT/ The system property shouldn't be a problem when it comes to testing the feature on a development machine.

Positive feedback would help towards getting this patch applied - then hopefully we could move on to discuss how best to configure this setting (be it a static method or another approach). Alternative patches would also welcome.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From tj.rothwell on January 17, 2011 16:42:36

In Tomcat 6.0.29, it doesn't find my defined class.

Finalizer.class.getClassLoader() is a java.net.URLClassLoader which would probably only be looking in jar.

I tried Thread.currentThread().getContextClassLoader() which is a org.apache.catalina.loader.WebappClassLoader and the class is loaded.

I didn't try other class loaders (e.g. Class.forName()).

From tj.rothwell on January 17, 2011 16:42:36

In Tomcat 6.0.29, it doesn't find my defined class.

Finalizer.class.getClassLoader() is a java.net.URLClassLoader which would probably only be looking in jar.

I tried Thread.currentThread().getContextClassLoader() which is a org.apache.catalina.loader.WebappClassLoader and the class is loaded.

I didn't try other class loaders (e.g. Class.forName()).

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on January 19, 2011 13:32:54

yes Thread.currentThread().getContextClassLoader() probably makes more sense

From mcculls on January 19, 2011 13:32:54

yes Thread.currentThread().getContextClassLoader() probably makes more sense

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on January 19, 2011 14:14:04

Prototype patch now tries to load the custom Executor from the TCCL before falling back to Class.forName

Attachment: gist
   GUICE_ISSUE_288_20110119.patch

From mcculls on January 19, 2011 14:14:04

Prototype patch now tries to load the custom Executor from the TCCL before falling back to Class.forName

Attachment: gist
   GUICE_ISSUE_288_20110119.patch

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From tj.rothwell on January 25, 2011 07:59:39

I must be missing something--does it make sense to have a custom executor? How does this solve the sticky references that prevents gc of the frq?

Using "NONE" solves it, but is there a way to have the Finalizer thread and still have the container not leak?

From tj.rothwell on January 25, 2011 07:59:39

I must be missing something--does it make sense to have a custom executor? How does this solve the sticky references that prevents gc of the frq?

Using "NONE" solves it, but is there a way to have the Finalizer thread and still have the container not leak?

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From fry@google.com on March 05, 2011 19:55:37

No fix yet. This issue will be updated when there is. :-)

From fry@google.com on March 05, 2011 19:55:37

No fix yet. This issue will be updated when there is. :-)

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From larrrs.jung on March 05, 2011 19:58:54

okay, thx for the reply :)

From larrrs.jung on March 05, 2011 19:58:54

okay, thx for the reply :)

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From nimbus4321 on March 07, 2011 14:07:10

Hi Fry,
I couldn't see the fix in the recent Guice 3 RC3 release - is it still going to make it into the GA release ?
thanks.

From nimbus4321 on March 07, 2011 14:07:10

Hi Fry,
I couldn't see the fix in the recent Guice 3 RC3 release - is it still going to make it into the GA release ?
thanks.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From fry@google.com on March 07, 2011 14:10:51

There is no fix yet. This issue will be updated when there is. :-/

From fry@google.com on March 07, 2011 14:10:51

There is no fix yet. This issue will be updated when there is. :-/

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From sberlin on March 07, 2011 14:30:03

It is unlikely the fix will be in Guice 3.0.  We'll update the Guice source with the latest Guava bits when it's available.

From sberlin on March 07, 2011 14:30:03

It is unlikely the fix will be in Guice 3.0.  We'll update the Guice source with the latest Guava bits when it's available.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From jennifer.anagrius on March 28, 2011 06:58:55

Are there any quick and dirty workarounds for this atm? I'm really in a bind here :(

From jennifer.anagrius on March 28, 2011 06:58:55

Are there any quick and dirty workarounds for this atm? I'm really in a bind here :(

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on March 28, 2011 09:51:21

One quick and dirty workaround would be to use the sisu-guice binary: http://repo1.maven.org/maven2/org/sonatype/sisu/sisu-guice/3.0.0/ This is guice 3.0 plus some patches ( https://github.com/sonatype/sisu-guice/blob/master/PATCHES ).

One of these changes is to add a property "-Dguice.executor.class=Clazz" where Clazz implements java.util.concurrent.Executor. You can then supply your own executor to manage the finalizer work. You can also use "-Dguice.executor.class=NONE" to turn off the finalizer completely, but note that this means cleanup will only happen occasionally when the weak collections mutate.

HTH  (sorry about the use of a property, I didn't want to introduce an experimental API that wasn't in Guice)

From mcculls on March 28, 2011 09:51:21

One quick and dirty workaround would be to use the sisu-guice binary: http://repo1.maven.org/maven2/org/sonatype/sisu/sisu-guice/3.0.0/ This is guice 3.0 plus some patches ( https://github.com/sonatype/sisu-guice/blob/master/PATCHES ).

One of these changes is to add a property "-Dguice.executor.class=Clazz" where Clazz implements java.util.concurrent.Executor. You can then supply your own executor to manage the finalizer work. You can also use "-Dguice.executor.class=NONE" to turn off the finalizer completely, but note that this means cleanup will only happen occasionally when the weak collections mutate.

HTH  (sorry about the use of a property, I didn't want to introduce an experimental API that wasn't in Guice)

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From bontecyril on March 31, 2011 04:56:28

As another workaround that doesn't require to patch guice sources, I've started to work on a Tomcat Listener that try to shutdown the thread when the context is destroyed. It also tries to cancel the Expiration Timer launched by MapMaker.

It looks to work correctly (with both guice 2.0 and 3.0) but I've not tested it in production yet. The code can easily be ported to other applications thant tomcat.

The Listener sources are in attachment (note that I removed the package name from the sources). Maybe it can be a starting point to be integrated in guice or tomcat, or in a "guice-utils" jar.

Attachment: gist
   GuiceLifecycleListener.java

From bontecyril on March 31, 2011 04:56:28

As another workaround that doesn't require to patch guice sources, I've started to work on a Tomcat Listener that try to shutdown the thread when the context is destroyed. It also tries to cancel the Expiration Timer launched by MapMaker.

It looks to work correctly (with both guice 2.0 and 3.0) but I've not tested it in production yet. The code can easily be ported to other applications thant tomcat.

The Listener sources are in attachment (note that I removed the package name from the sources). Maybe it can be a starting point to be integrated in guice or tomcat, or in a "guice-utils" jar.

Attachment: gist
   GuiceLifecycleListener.java

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From jose.illescas on May 09, 2011 02:37:09

@bontecy, I test your GuiceLifecycleListener on my Tomcat (development environment) without any Permgen errors on redeploys... GREAT!!

From jose.illescas on May 09, 2011 02:37:09

@bontecy, I test your GuiceLifecycleListener on my Tomcat (development environment) without any Permgen errors on redeploys... GREAT!!

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From bontecyril on May 09, 2011 05:59:05

Ok, great. Note that I found a conflict with this workaround when a second context provides the jars but don't use them : the listener then initializes the thread for that context while it tries to stop the thread of the first context. Also, the loops are not optimal.
I didn't find time to fix this for now but I'll try to address this if no solution comes soon in guice (Then, I'll probably create a repository outside of this bug report).

From bontecyril on May 09, 2011 05:59:05

Ok, great. Note that I found a conflict with this workaround when a second context provides the jars but don't use them : the listener then initializes the thread for that context while it tries to stop the thread of the first context. Also, the loops are not optimal.
I didn't find time to fix this for now but I'll try to address this if no solution comes soon in guice (Then, I'll probably create a repository outside of this bug report).

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From fry@google.com on June 13, 2011 07:11:26

The fix for this has finally landed in Guava, and will be deployed in release 10.

From fry@google.com on June 13, 2011 07:11:26

The fix for this has finally landed in Guava, and will be deployed in release 10.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From henrychankinwo on July 12, 2011 18:09:04

Will there be a new Guice release containing this fix?

From henrychankinwo on July 12, 2011 18:09:04

Will there be a new Guice release containing this fix?

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From jose.illescas on September 29, 2011 04:14:39

Now guava (10) fixed this issue. Any plan/roadmap to include this fix on guice?

From jose.illescas on September 29, 2011 04:14:39

Now guava (10) fixed this issue. Any plan/roadmap to include this fix on guice?

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From colin.taylor on October 02, 2011 18:12:38

Any word on a fix? Nothing mentioned so far works for me..

From colin.taylor on October 02, 2011 18:12:38

Any word on a fix? Nothing mentioned so far works for me..

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on October 02, 2011 18:36:18

You could always try sisu-guice 3.1.0 (which is guice + a few experimental patches, such as the guava update) http://search.maven.org/#artifactdetails%7Corg.sonatype.sisu%7Csisu-guice%7C3.1.0%7Cjar Note that this depends on sisu-guava 0.9.9 - which was based on pre-10 build of guava with the finalizer thread fix, but you can always substitute this with guava 10 now that's been released. Also unlike previous releases this particular flavour of guice doesn't embed/jarjar guava code, so you do need both on the classpath.

From mcculls on October 02, 2011 18:36:18

You could always try sisu-guice 3.1.0 (which is guice + a few experimental patches, such as the guava update) http://search.maven.org/#artifactdetails%7Corg.sonatype.sisu%7Csisu-guice%7C3.1.0%7Cjar Note that this depends on sisu-guava 0.9.9 - which was based on pre-10 build of guava with the finalizer thread fix, but you can always substitute this with guava 10 now that's been released. Also unlike previous releases this particular flavour of guice doesn't embed/jarjar guava code, so you do need both on the classpath.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on October 07, 2011 03:49:10

Minor patch to update Guava dependency to 10.0

Attachment: gist
   update_to_guava_10.patch
Binary attachments: guava-10.0.jar

From mcculls on October 07, 2011 03:49:10

Minor patch to update Guava dependency to 10.0

Attachment: gist
   update_to_guava_10.patch
Binary attachments: guava-10.0.jar

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From jose.illescas on October 26, 2011 04:03:12

Great work mcculls,

 But i like some plan/roadmap to include this fix on "original" guice?

For example: a "official" guice 3.1 release to resolve all Accepted issues with Hight priority must be one ideal solution...

From jose.illescas on October 26, 2011 04:03:12

Great work mcculls,

 But i like some plan/roadmap to include this fix on "original" guice?

For example: a "official" guice 3.1 release to resolve all Accepted issues with Hight priority must be one ideal solution...

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on November 10, 2011 11:25:10

Issue 630 has been merged into this issue.

From mcculls on November 10, 2011 11:25:10

Issue 630 has been merged into this issue.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From jose.illescas on November 11, 2011 09:20:48

@mcculls,

I try your patch with guava-10.0 but tomcat persist on:

[16] SEVE 18:16:32 WebappClassLoader.checkThreadLocalMapForLeaks: The web application [/ulysses] created a ThreadLocal with key of type [com.google.inject.internal.InjectorImpl$1] (value [com.google.inject.internal.InjectorImpl$1@125ec471]) and a value of type [java.lang.Object[]] (value [[Ljava.lang.Object;@bb2e023]) 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.
[16] SEVE 18:16:32 WebappClassLoader.checkThreadLocalMapForLeaks: The web application [/ulysses] created a ThreadLocal with key of type [com.google.inject.internal.InjectorImpl$1] (value [com.google.inject.internal.InjectorImpl$1@125ec471]) and a value of type [java.lang.Object[]] (value [[Ljava.lang.Object;@c991fd5]) 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.

Any fix/idea?

From jose.illescas on November 11, 2011 09:20:48

@mcculls,

I try your patch with guava-10.0 but tomcat persist on:

[16] SEVE 18:16:32 WebappClassLoader.checkThreadLocalMapForLeaks: The web application [/ulysses] created a ThreadLocal with key of type [com.google.inject.internal.InjectorImpl$1] (value [com.google.inject.internal.InjectorImpl$1@125ec471]) and a value of type [java.lang.Object[]] (value [[Ljava.lang.Object;@bb2e023]) 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.
[16] SEVE 18:16:32 WebappClassLoader.checkThreadLocalMapForLeaks: The web application [/ulysses] created a ThreadLocal with key of type [com.google.inject.internal.InjectorImpl$1] (value [com.google.inject.internal.InjectorImpl$1@125ec471]) and a value of type [java.lang.Object[]] (value [[Ljava.lang.Object;@c991fd5]) 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.

Any fix/idea?

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From stefan.simroth on November 11, 2011 09:27:37

Hi,
I resolved the issue for me by compiling sisu-guice (master) with the guava 10.0.1 dependency (instead of the sisu-guava 0.9.9).
See here: https://github.com/sas101/sisu-guice/commit/2bc6e1554d29faf95df3cb959d258456ceaf060a Thx @mcculls for providing that suggestion.

From stefan.simroth on November 11, 2011 09:27:37

Hi,
I resolved the issue for me by compiling sisu-guice (master) with the guava 10.0.1 dependency (instead of the sisu-guava 0.9.9).
See here: https://github.com/sas101/sisu-guice/commit/2bc6e1554d29faf95df3cb959d258456ceaf060a Thx @mcculls for providing that suggestion.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on November 11, 2011 09:34:20

As explained above the remaining ThreadLocal of type Object[1] seen by Tomcat is not a memory leak and would eventually get cleared. However, even if it wasn't cleared it only takes up a few bytes and would not hold onto any user level classloaders, which is the cause of most leaks. This is because the single element in that array is guaranteed to be null'd out in a finally clause and the component type of the array is Object.

Note: the reason the ThreadLocal is left between injector calls and not removed on every call is for performance reasons. Explicitly removing a ThreadLocal is not mandated as shown in the example from the official javadocs http://download.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html because it should automatically get cleared when the ThreadLocal is no longer accessible. Unfortunately the JDK is slow in clearing out stale entries, which coupled with the (overly) zealous checks in Tomcat can lead to these spurious error messages (which should really be warnings imho).

From mcculls on November 11, 2011 09:34:20

As explained above the remaining ThreadLocal of type Object[1] seen by Tomcat is not a memory leak and would eventually get cleared. However, even if it wasn't cleared it only takes up a few bytes and would not hold onto any user level classloaders, which is the cause of most leaks. This is because the single element in that array is guaranteed to be null'd out in a finally clause and the component type of the array is Object.

Note: the reason the ThreadLocal is left between injector calls and not removed on every call is for performance reasons. Explicitly removing a ThreadLocal is not mandated as shown in the example from the official javadocs http://download.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html because it should automatically get cleared when the ThreadLocal is no longer accessible. Unfortunately the JDK is slow in clearing out stale entries, which coupled with the (overly) zealous checks in Tomcat can lead to these spurious error messages (which should really be warnings imho).

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From balint@krivan.info on July 12, 2012 00:10:51

Using Guice 3.0 from central maven repo I am still getting this:

2012.07.12. 9:00:18 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/foo-bar-1.0-SNAPSHOT] appears to have started a thread named [com.google.inject.internal.util.$Finalizer] but has failed to stop it. This is very likely to create a memory leak.

Any news on this? I don't see guava dependency in the pom, but I've read it will be fixed once it is upgraded. Thanks!

From balint@krivan.info on July 12, 2012 00:10:51

Using Guice 3.0 from central maven repo I am still getting this:

2012.07.12. 9:00:18 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/foo-bar-1.0-SNAPSHOT] appears to have started a thread named [com.google.inject.internal.util.$Finalizer] but has failed to stop it. This is very likely to create a memory leak.

Any news on this? I don't see guava dependency in the pom, but I've read it will be fixed once it is upgraded. Thanks!

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on July 20, 2012 11:11:56

Note that Guice 3.0 still embeds an old version of Guava (which is why the pom has no explicit dependency to it) so that message is expected.

From mcculls on July 20, 2012 11:11:56

Note that Guice 3.0 still embeds an old version of Guava (which is why the pom has no explicit dependency to it) so that message is expected.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From pas256 on July 20, 2012 11:17:52

OMG, we are getting close to 4 years old for this one... way to go Google!

From pas256 on July 20, 2012 11:17:52

OMG, we are getting close to 4 years old for this one... way to go Google!

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on July 20, 2012 11:23:14

PS. you you can always use sisu-guice (which doesn't embed guava, but instead has it as a dependency) http://search.maven.org/#artifactdetails%7Corg.sonatype.sisu%7Csisu-guice%7C3.1.1%7Cjar Or you could compile from source - also note in many scenarios the finalizer thread is not actually an issue.

From mcculls on July 20, 2012 11:23:14

PS. you you can always use sisu-guice (which doesn't embed guava, but instead has it as a dependency) http://search.maven.org/#artifactdetails%7Corg.sonatype.sisu%7Csisu-guice%7C3.1.1%7Cjar Or you could compile from source - also note in many scenarios the finalizer thread is not actually an issue.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From s.a.grigoriev on July 28, 2012 07:51:18

This definitely needs to be fixed.

From s.a.grigoriev on July 28, 2012 07:51:18

This definitely needs to be fixed.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on August 06, 2012 18:25:21

Here's an additional patch that clears up the last of the Tomcat warnings after upgrading to the latest Guava (the ones referring to the injectorImpl's ThreadLocal). The issue here was the injector used an anonymous class to define a custom initialValue method for its localContext ThreadLocal. Unfortunately this anonymous class has an implicit reference (seen as this$0 in the bytecode) back to the instance where it was created, ie. the injector. We could change this to be a static nested class which would avoid the reference to the injector, but this still keeps a reference back to the containing classloader which upsets Tomcat's strict checks. This patch removes the custom ThreadLocal subclass and adds a check+set in the callInContext method - note this is slightly less performant, since it needs an extra call to set(). It's questionable whether this performance hit is worth getting rid of all the Tomcat warnings, switching to a static nested class may be enough since you'd still occasionally see a warning but the only thing that a rogue thread local might be holding onto would be the classloader. Anyway, here's the patch in case anyone is interested in trying it out with trunk...

Attachment: gist
   GUICE_288_decouple_thread_local.patch

From mcculls on August 06, 2012 18:25:21

Here's an additional patch that clears up the last of the Tomcat warnings after upgrading to the latest Guava (the ones referring to the injectorImpl's ThreadLocal). The issue here was the injector used an anonymous class to define a custom initialValue method for its localContext ThreadLocal. Unfortunately this anonymous class has an implicit reference (seen as this$0 in the bytecode) back to the instance where it was created, ie. the injector. We could change this to be a static nested class which would avoid the reference to the injector, but this still keeps a reference back to the containing classloader which upsets Tomcat's strict checks. This patch removes the custom ThreadLocal subclass and adds a check+set in the callInContext method - note this is slightly less performant, since it needs an extra call to set(). It's questionable whether this performance hit is worth getting rid of all the Tomcat warnings, switching to a static nested class may be enough since you'd still occasionally see a warning but the only thing that a rogue thread local might be holding onto would be the classloader. Anyway, here's the patch in case anyone is interested in trying it out with trunk...

Attachment: gist
   GUICE_288_decouple_thread_local.patch

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on August 07, 2012 12:00:50

Issue 698 has been merged into this issue.

From mcculls on August 07, 2012 12:00:50

Issue 698 has been merged into this issue.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From nicolas.antoniazzi on August 24, 2012 02:01:51

I tried the last version from trunk + the patch from Stuart McCulloch, and it works now perfectly.
This patch should be integrated to guice.

Thanks

From nicolas.antoniazzi on August 24, 2012 02:01:51

I tried the last version from trunk + the patch from Stuart McCulloch, and it works now perfectly.
This patch should be integrated to guice.

Thanks

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on September 02, 2012 03:32:55

Issue 698 has been merged into this issue.

From mcculls on September 02, 2012 03:32:55

Issue 698 has been merged into this issue.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From lorenzom on January 21, 2013 07:57:37

If the proposed decoupling thread local patch is the fix we need and want, then wouldn't it be more conservative to declare a static concrete inner class for the LocalContext ? We would not need to change the lifecycle of InjectorImpl.localContext.

Attachment: gist
   GUICE_288_static_concrete_class.patch

From lorenzom on January 21, 2013 07:57:37

If the proposed decoupling thread local patch is the fix we need and want, then wouldn't it be more conservative to declare a static concrete inner class for the LocalContext ? We would not need to change the lifecycle of InjectorImpl.localContext.

Attachment: gist
   GUICE_288_static_concrete_class.patch

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on February 27, 2013 15:12:40

As mentioned in #c88 using a static nested class would still leave an indirect reference to the guice classloader which would be picked up by Tomcat's memory leak detector. So if you wanted to remove all warnings then the patch in #c88 is the best I've found so far.

From mcculls on February 27, 2013 15:12:40

As mentioned in #c88 using a static nested class would still leave an indirect reference to the guice classloader which would be picked up by Tomcat's memory leak detector. So if you wanted to remove all warnings then the patch in #c88 is the best I've found so far.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From ryan@asleson.net on October 16, 2013 05:35:18

So this bug has not been fixed in the Guice 4.0 beta, correct?  So is it correct to assume that it won't make it into 4.0 GA?  Bummer.

From ryan@asleson.net on October 16, 2013 05:35:18

So this bug has not been fixed in the Guice 4.0 beta, correct?  So is it correct to assume that it won't make it into 4.0 GA?  Bummer.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on October 16, 2013 06:00:36

Guice 4.0-beta embeds Guava 11.0.1, which includes the FinalizableReferenceQueue fix. You may still see a warning in Tomcat about a ThreadLocal (see comment #c88 and associated patch) but this is relatively minor compared to the original issue.

From mcculls on October 16, 2013 06:00:36

Guice 4.0-beta embeds Guava 11.0.1, which includes the FinalizableReferenceQueue fix. You may still see a warning in Tomcat about a ThreadLocal (see comment #c88 and associated patch) but this is relatively minor compared to the original issue.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From cowwoc@bbs.darktech.org on October 16, 2013 08:10:20

All of this could have been solved 6 (!!) years ago by simply adding a close() method. See comment #3.

Add a close() method now and remove it in the future if you ever get an alternative working.

From cowwoc@bbs.darktech.org on October 16, 2013 08:10:20

All of this could have been solved 6 (!!) years ago by simply adding a close() method. See comment #3.

Add a close() method now and remove it in the future if you ever get an alternative working.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on October 16, 2013 08:21:22

There's no need for a close() method now - the weak/soft maps were re-implemented in Guava 10 to avoid the need for the FRQ background thread, so there is literally nothing to close: https://code.google.com/p/guava-libraries/source/detail?r=a13e02167e90125e6a78bf9bbd061996d05a143a . The FRQ fix is available in Guice 4.0-beta for testing.

From mcculls on October 16, 2013 08:21:22

There's no need for a close() method now - the weak/soft maps were re-implemented in Guava 10 to avoid the need for the FRQ background thread, so there is literally nothing to close: https://code.google.com/p/guava-libraries/source/detail?r=a13e02167e90125e6a78bf9bbd061996d05a143a . The FRQ fix is available in Guice 4.0-beta for testing.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on December 01, 2013 17:23:50

Issue 786 has been merged into this issue.

From mcculls on December 01, 2013 17:23:50

Issue 786 has been merged into this issue.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From sberlin on December 05, 2013 15:51:07

Issue 707 has been merged into this issue.

From sberlin on December 05, 2013 15:51:07

Issue 707 has been merged into this issue.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mvdgraaf on March 01, 2014 06:12:14

I see that there have been multiple attempts to fix the localContext variable in the InjectorImpl. But sadly they all fail to solve the issue completely and specially in a Servlet container.

In tomcat there is still a warning (also in 4.0-beta) because the ThreadLocal is not cleared (the object[] is still leaked into the Threads).

With the current JVM's it requires a new ThreadLocal to do something to finally garbage collect  ThreadLocal's values from the Thread class and each thread needs to get hit with that new ThreadLocal to completely cleanup the mess left behind by other ThreadLocal's this can take some time for an application server like tomcat because it can run 100+ Thread's and there is no guarantee that the Thread will ever hit a new ThreadLocal.

To solve these issues we need to clear the ThreadLocal and must not use a library/application extends class to initialize the ThreadLocal.

The attached patch file removes the LocalContextThreadLocal, removes the unnecessary Object[] and clears the ThreadLocal.

Attachment: gist
   ThreadLocalFix-guice.patch

From mvdgraaf on March 01, 2014 06:12:14

I see that there have been multiple attempts to fix the localContext variable in the InjectorImpl. But sadly they all fail to solve the issue completely and specially in a Servlet container.

In tomcat there is still a warning (also in 4.0-beta) because the ThreadLocal is not cleared (the object[] is still leaked into the Threads).

With the current JVM's it requires a new ThreadLocal to do something to finally garbage collect  ThreadLocal's values from the Thread class and each thread needs to get hit with that new ThreadLocal to completely cleanup the mess left behind by other ThreadLocal's this can take some time for an application server like tomcat because it can run 100+ Thread's and there is no guarantee that the Thread will ever hit a new ThreadLocal.

To solve these issues we need to clear the ThreadLocal and must not use a library/application extends class to initialize the ThreadLocal.

The attached patch file removes the LocalContextThreadLocal, removes the unnecessary Object[] and clears the ThreadLocal.

Attachment: gist
   ThreadLocalFix-guice.patch

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Jul 7, 2014

From mcculls on March 01, 2014 06:18:53

IIRC the use of the holder array was for performance reasons, but there is a way to keep the holder array and still avoid the implicit classloader reference and associated Tomcat warning: https://github.com/sonatype/sisu-guice/blob/master/PATCHES/GUICE_288_decouple_thread_local.patch

From mcculls on March 01, 2014 06:18:53

IIRC the use of the holder array was for performance reasons, but there is a way to keep the holder array and still avoid the implicit classloader reference and associated Tomcat warning: https://github.com/sonatype/sisu-guice/blob/master/PATCHES/GUICE_288_decouple_thread_local.patch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment