Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding running instances in a running JVM

I'm wondering if it's possible to get a handle on running instances of a given class. The particular issue that triggered this was an application that doesn't exit nicely because of a number of running threads.

Yes, I know you can daemonize the theads, and they won't then hold up the application exit. But it did get me to wondering if this was possible. The closest thing I can is the classloaders (protected!) findLoadedClass, although you'd have to run through your own classloader to do this.

On a related note, is this how profiling tools manage to track object handles? by running through their own custom classloaders? or is there some nice tricky way that I'm not seeing?

like image 792
Steve B. Avatar asked Dec 22 '22 13:12

Steve B.


1 Answers

You can indeed get a stack trace of all running Threads dumped to the stdout by using kill -QUIT <pid> on a *NIX like OS, or by running the application in a Windows console and pressing Ctrl-Pause (as another poster notes.)

However, it seems like you're asking for programmatic ways to do it. So, assuming what you really want is the set of all Threads who's current call stacks include one or more methods from a given class...

The best thing I can find that doesn't involve calls into the JVMTI is to inspect the stacks of all running threads. I haven't tried this, but it should work in Java 1.5 and later. Keep in mind that this is, by definition, not AT ALL thread-safe (the list of running threads - and their current stack traces - are going to constantly change underneath you...lots of paranoid stuff would be necessary to actually make use of this list.)

public Set<Thread> findThreadsRunningClass(Class classToFindRunning) {

  Set<Thread> runningThreads = new HashSet<Thread>();
  String className = classToFindRunning.getName();

  Map<Thread,StackTraceElement[]> stackTraces = Thread.getAllStackTraces();
  for(Thread t : stackTraces.keySey()) {
    StackTraceElement[] steArray = stackTraces.get(t);
    for(int i = 0;i<steArray.size();i++) {
      StackTraceElement ste = steArray[i];
      if(ste.getClassName().equals(className)) {
        runningThreads.add(t);
        continue;
      }
    }
  }

  return runningThreads;
}

Let me know if this approach works out for you!

like image 173
Jared Avatar answered Jan 04 '23 08:01

Jared