org.jolokia.jvmagent.CleanupThread Maven / Gradle / Ivy
The newest version!
package org.jolokia.jvmagent;
/*
* Copyright 2009-2013 Roland Huss
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import com.sun.net.httpserver.HttpServer;
/**
* Thread for stopping the HttpServer configured as {@link Runtime#addShutdownHook(Thread)}.
*
* @author roland
* @since Mar 3, 2010
*/
class CleanupThread extends Thread {
private final HttpServer server;
private final ThreadGroup threadGroup;
private boolean active = true;
/**
* Constructor associating the cleanup thread with an HTTP-Server
*
* @param pServer HTTP server to observe
* @param pThreadGroup thread group needed for proper cleanup
*/
CleanupThread(HttpServer pServer, ThreadGroup pThreadGroup) {
super("Jolokia Agent Cleanup Thread");
server = pServer;
threadGroup = pThreadGroup;
setDaemon(true);
}
/** {@inheritDoc} */
@Override
public void run() {
server.stop(0);
}
/**
* Stop the server.
*/
public void stopServer() {
active = false;
server.stop(0);
}
// Enumerate all active threads
private Thread[] enumerateThreads() {
boolean fits = false;
int inc = 50;
Thread[] threads = null;
int nrThreads = 0;
while (!fits) {
try {
threads = new Thread[Thread.activeCount()+inc];
nrThreads = Thread.enumerate(threads);
fits = true;
} catch (ArrayIndexOutOfBoundsException exp) {
inc += 50;
}
}
// Trim array
Thread[] ret = new Thread[nrThreads];
System.arraycopy(threads,0,ret,0,nrThreads);
return ret;
}
// Join threads, return false if only our own threads are left.
private boolean joinThreads(Thread[] pThreads) {
for (final Thread t : pThreads) {
if (isDaemonLikeThread(t)) {
continue;
}
try {
t.join();
} catch (Exception ex) {
// Ignore that one.
}
// We just joined a 'foreign' thread, so we redo the loop
return true;
}
// All 'foreign' threads has finished, hence we are prepared to stop
return false;
}
private static final String[] DAEMON_THREAD_NAMES = new String[] {
// Tanuki Java Service Wrapper (#116)
"WrapperListener_stop_runner",
// Shutdown thread
"DestroyJavaVM"
}; // Check for threads which should not prevent the server from stopping.
private boolean isDaemonLikeThread(Thread pThread) {
// Daemon or part of our thread group
if (pThread.isDaemon() ||
pThread.getThreadGroup() == null || // has died on us
pThread.getThreadGroup().equals(threadGroup)) {
return true;
}
for (String name : DAEMON_THREAD_NAMES) {
if (pThread.getName().startsWith(name)) {
return true;
}
}
return false;
}
}