Comments inline with ==== COMMENT ====

On 8/28/2012 8:19 AM, Christopher Schultz wrote:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Mark,

On 8/27/12 6:07 PM, Mark Eggers wrote:
>On 8/27/2012 1:24 PM, Christopher Schultz wrote:
>>
>>Hmm... that's ... not supposed to happen. The AppContext
>>leak-prevention has been in Tomcat since back in 2009. Can you
>>confirm that the JreMemoryLeakProtectionListener is actually
>>being loaded?
>
>A heap dump (jvisualvm) on the following environments show one
>instance of the class being loaded.
That's good!

>1. Windows 7, JRE 1.7.0_05, Tomcat 6.0.35 2. Windows 7, JRE
>1.7.0_05, Tomcat 7.0.27 3. Windows 7, JRE 1.6.0_32, Tomcat 6.0.35
>4. Windows 7, JRE 1.6.0_32, Tomcat 7.0.27 5. CentOS 6.3, JRE
>1.6.0_32, Tomcat 6.0.35, -Djava.awt.headless=true this is actually
>running X Windows though 6. CentOS 5.8, JRE 1.6.0_32, Tomcat
>6.0.35, -Djava.awt.headless=true not running X Windows (dump via
>jmap)
>
>Hmm - looking at Tomcat 6.0.35 on the CentOS 5.8 system, I see the
>following when looking at the instance of
>JreMemoryProtectionListener.
>
>appContextProtection (Z) : true awtThreadProtection (Z) : true
appContextProtection=true is the default and awtThreadProtection=true
is*not*  the default. I would say that this is the proper
configuration for what you are trying to solve. In that case, can you
check the ClassLoader used for the AppContext and AWT threads?
==== COMMENT ====

Interesting thought. So you suspect that even with the JreMemoryLeakPreventionListener loaded, it's not taking care of the AppContext?

I just took a look at one of my heap dumps.

AppContext has one instance loaded. The contextClassLoader field is set to Launcher$AppClassLoader, which is what you would expect.

EventQueue has one instance loaded. The contextClassLoader field is set to Launcher$AppClassLoader, which is what you would expect.

==== COMMENT ====

>And I do have the attribute set to manage the AWT thread (at least
>on the Tomcat I dumped).
>
>On the Windows (Tomcat 6.0.35, JRE 1.6.0_32), I see the following:
>
>appContextProtection (Z) : true awtThreadProtection (Z) : false
>classesToInitialize (L) : <null> driverManagerProtection (Z) :
>true gcDaemonProtection (Z) : true ldapPoolProtection (Z) : true
>securityLoginConfigurationProtection (Z) : true
>securityPolicyProtection (Z) : true tokenPollerProtection (Z) :
>true urlCacheProtection (Z) : true xmlParsingProtection (Z) : true
>
>which is what I expect from server.xml.
So the server.xml has awtThreadProtection=false (or just uses the
default)?

>Commenting out the listener (actually it doesn't matter either way
>since I'm running in a windowed environment) and adding the AWT
>Event thread protection produces on Windows:
>
>appContextProtection (Z) : true awtThreadProtection (Z) : true
>classesToInitialize (L) : <null> driverManagerProtection (Z) :
>true gcDaemonProtection (Z) : true ldapPoolProtection (Z) : true
>securityLoginConfigurationProtection (Z) : true
>securityPolicyProtection (Z) : true tokenPollerProtection (Z) :
>true urlCacheProtection (Z) : true xmlParsingProtection (Z) : true
If you comment-out the listener, they why is the class loaded at all?
Are you sure everything in your environment is sane?

==== COMMENT ====

Sorry, this is probably one of the few times I was less than careful with my writing. I meant to say that I removed the listener with the attribute (AWTThreadProtection="true") and used the default configuration.

I actually have both in server.xml. I just comment out whichever one I'm not testing at the moment.

Hopefully that's a bit clearer :-p.

==== COMMENT ====
>And I still see the exact same permgen memory leak upon unloading
>the application.
>
>The problem looks to be in an internal use of MediaTracker. I
>suspect that the library uses this to speed image recovery should
>there be repeated calls.
IIRC MediaTracker is a concurrent component that loads stuff (like
images) in the background and sends update-events to interested
components. Perhaps there is yet another thread that needs to be
managed on top of the AWT thread. Can you take a thread dump and
possibly indicate the ClassLoader for each thread?

==== COMMENT ====

I'll go poke around the heap dump and see what I find. Possibly look at each thread and find the classloader ? Sigh, that's a pain.

I'll also do a thread dump while the application is running to see if any strange threads appear.

My immediate guess (from reading the AWT model) is that there will not be another thread.

==== COMMENT ====
>Unfortunately, these images are dynamically generated, so any use
>of MediaTracker is pretty worthless in this use case.
I've found that use of the MediaTracker is entirely worthless except
when using GUIs that need to display images within components (like
buttons, etc.). Anyone using MediaTracker in a client-side library is
making a mistake (that is, your 3rd-party library is either not
targeted towards a server-side application, or the devs don't know
what they are doing).

>There's a way to purge the library caches, and I've experimented
>with that as well. Unfortunately, it doesn't unregister the images
>it stored in the MediaTracker. In short, flushing the library's
>cache in this use case does not address the problem.
Fantastic.
==== COMMENT ====

Well, fantastic isn't quite the word I'd use . . . .

I wonder what would happen if I used the classesToInitialize attribute of the JreMemoryLeakPreventionListner, and gave it java.awt.MediaTracker?

Still, the images would be loaded (although they're small). However, a quick glance at the Image class doesn't reveal why that class would retain any references to the classes that added them to the MediaTracker. I'd just get a bunch of images stuffed into memory, but not the rest of the web application.

In short, I'd still get a slow (or fast - depending on application usage) memory leak. It would just leave a bit less around when I unloaded the application (possibly).

This is also a hack, in that I may or may not be able to do this on the target server. However, I could look at the listener code and duplicate that in my listener that starts up the AWT thread.

==== COMMENT ====

- -chris

. . . . rabbit holes, don't tumble down them.
/mde/

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to