简体   繁体   中英

How to identify the cause of a JNI global reference memory leak?

I'm using Tomcat and after stopping my web application there's still a reference to the classloader instance of my web application. With the consequence that a notable amount of memory (mostly related to static data) will not be freed. Sooner or later this results in an OutOfMemoryError .

I took a heap dump and I realized that its held by a JNI global reference which prevents that the classloader will be garbage collected .

My application does not use JNI . I am also not using the Apache Tomcat Native Library . I am using a Sun/Oracle JDK.
I'd like to track down the cause/origin of this global reference. (My guess is that the JVM internally references the classloader - but why/where?).

Question:

  • Which approaches/toolsets exists to achieve this?

UPDATE

It seems that bestsss is right and the JNI global references has been introduced by the jvm debug mode. This helped me out but it does not answer the question so I am still curious to get an answer to the question which might be helpful in the future.

Besides the obvious case: Threads, there is one more:

Are you using your application in debug mode?

The JVM does not hold references to any classloader besides the system one, but it doesn't concern you. The rest of JNI references are either Threads or just debug held objects (provided you don't use JNI and lock the objects down yourself).

JNI references are just roots, edit your answer and post what exactly objects are held by those references.

The first thing i'd do is run with -Xcheck:jni on and see if it comes up with anything. I wouldn't expect it to; it doesn't sound there's anything weird happening with JNI, just incorrect use being made of it. However, it's good to make sure of that.

If you're on a Sun JVM, i think you can do -XX:TraceJNICalls to get an overwhelming listing of JNI calls as they happen. That should let you get an idea of what calls are being made, and from there work towards what is making them, and why this is causing a problem.

JRockit mission control: http://download.oracle.com/docs/cd/E13150_01/jrockit_jvm/jrockit/tools/index.html

A nice GUI tool that should help you find it pretty quick.

You could try jstack .

Maybe one of the listed stacktraces will show you the origin of the global reference.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM