All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.mhus.karaf.commands.shell.CmdThreads Maven / Gradle / Ivy

There is a newer version: 6.4.0
Show newest version
/**
 * Copyright 2018 Mike Hummel
 *
 * 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.
 */
package de.mhus.karaf.commands.shell;

import java.lang.Thread.State;
import java.lang.management.LockInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.karaf.shell.api.action.Action;
import org.apache.karaf.shell.api.action.Argument;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.Option;
import org.apache.karaf.shell.api.action.lifecycle.Service;

import de.mhus.lib.core.MCast;
import de.mhus.lib.core.console.ConsoleTable;

@Command(scope = "java", name = "thread", description = "Print thread information")
@Service
public class CmdThreads implements Action {

	@Argument(index=0, name="thread", required=false, description="Thread Id", multiValued=false)
    String threadId;

	@Argument(index=1, name="action", required=false, description="suspend, resume, stop, destroy, interrupt, priority ", multiValued=false)
    String action;
	
	@Argument(index=2, name="arguments", required=false, description="arguments", multiValued=true)
    String arguments[];
	
    @Option(name = "-s", aliases = { "--stacktrace" }, description = "print also stack traces", required = false, multiValued = false)
    boolean stackAlso;
	
    @Option(name = "-i", aliases = { "--orderid" }, description = "order by id", required = false, multiValued = false)
    boolean orderId;
    
    @Option(name = "-n", aliases = { "--ordername" }, description = "order by name", required = false, multiValued = false)
    boolean orderName;
    
    @Option(name = "-g", aliases = { "--ordergroup" }, description = "order by group", required = false, multiValued = false)
    boolean orderGroup;
    
    @Option(name = "-r", aliases = { "--running" }, description = "Running only", required = false, multiValued = false)
    boolean running;
    
	ThreadMXBean tmxb = ManagementFactory.getThreadMXBean();

	@SuppressWarnings("deprecation")
	@Override
	public Object execute() throws Exception {

		Map traces = Thread.getAllStackTraces();
		
		List threadList = new LinkedList<>(traces.keySet());
		
		if (running)
			threadList.removeIf(i -> { return i.getState() != State.RUNNABLE; });
		
		if (orderId) {
			Collections.sort(threadList, new Comparator() {

				@Override
				public int compare(Thread o1, Thread o2) {
					return Long.compare(o1.getId(), o2.getId());
				}
			});
		}
		
		if (orderName) {
			Collections.sort(threadList, new Comparator() {

				@Override
				public int compare(Thread o1, Thread o2) {
					return o1.getName().compareTo(o2.getName());
				}
			});
		}
		
		if (orderGroup) {
			Collections.sort(threadList, new Comparator() {

				@Override
				public int compare(Thread o1, Thread o2) {
					return o1.getThreadGroup().getName().compareTo(o2.getThreadGroup().getName());
				}
			});
		}

		ConsoleTable table = new ConsoleTable();
		table.setHeaderValues("Id", "Name", "Group","Status", "Prio","Alive","Daemon");
		
		if (threadId == null) {
			
			for (Thread thread : threadList) {
				printThread(thread, table);
				if (stackAlso) {
					StackTraceElement[] stack = traces.get(thread);
					printStack(stack, table);
				}
			}
			
		} else
		if (action != null) {
			for (Thread thread : traces.keySet()) {
				if (String.valueOf(thread.getId()).equals(threadId) || thread.getName().equals(threadId) || threadId.equals("current") && thread == Thread.currentThread() ) {
					switch (action) {
					case "suspend": {
						System.out.println("SUSPEND " + thread.getId() + " " + thread.getName());
						thread.suspend();
					} break;
					case "resume": {
						System.out.println("RESUME " + thread.getId() + " " + thread.getName());
						thread.resume();
					} break;
					case "stop": {
						System.out.println("STOP " + thread.getId() + " " + thread.getName());
						thread.stop();
					} break;
					case "interrupt": {
						System.out.println("INTERRUPT " + thread.getId() + " " + thread.getName());
						thread.interrupt();
					} break;
					case "kill": {
						String message = arguments[0];
						Throwable exception = new Throwable(message);
						if (arguments.length > 1) {
							exception = (Throwable) Class.forName(arguments[1]).getConstructor(String.class).newInstance(message);
						}
						System.out.println("STOP " + thread.getId() + " " + thread.getName() + " by " + exception);
						thread.stop();
					} break;
					case "destroy": {
						System.out.println("DESTROY " + thread.getId() + " " + thread.getName());
						// thread.destroy();
					} break;
					case "priority": {
						System.out.println("PRIORITY " + thread.getId() + " " + thread.getName() + " = " + arguments[0]);
						thread.setPriority(MCast.toint(arguments[0], thread.getPriority()));
					} break;
					}
				}
			}
		} else {
			for (Thread thread : traces.keySet()) {
				if (String.valueOf(thread.getId()).equals(threadId) || thread.getName().equals(threadId) || threadId.equals("current") && thread == Thread.currentThread() ) {
					printThread(thread, table);
					StackTraceElement[] stack = traces.get(thread);
					printStack(stack,table);
					
					ThreadInfo info = tmxb.getThreadInfo(thread.getId());
					table.addRowValues("LockOwnerName","" + info.getLockOwnerName() ,"","","","");
					table.addRowValues("LockOwnerId","" + info.getLockOwnerId() ,"","","","");
					table.addRowValues("LockName","" + info.getLockName() ,"","","","");
					table.addRowValues("BlockedCount","" + info.getBlockedCount() ,"","","","");
					table.addRowValues("BlockedTime","" + info.getBlockedTime() ,"","","","");
					table.addRowValues("WaitedCount","" + info.getWaitedCount() ,"","","","");
					table.addRowValues("WaitedTime","" + info.getWaitedTime() ,"","","","");
					table.addRowValues("LockInfo","" + info.getLockInfo() ,"","","","");
					for (MonitorInfo lock : info.getLockedMonitors()) {
						table.addRowValues("Monitor","" + lock.getClassName() ,"" + lock.getIdentityHashCode(),"" + lock.getLockedStackDepth(),"","");
						table.addRowValues("","  at " + lock.getLockedStackFrame(),"","","","");
					}
					for (LockInfo lock : info.getLockedSynchronizers()) {
						table.addRowValues("Synchronizers","" + lock.getClassName(), "" + lock.getIdentityHashCode(), "", "", "");
					}
				}
			}
			
		}
		table.print(System.out);
		return null;
	}

	private void printStack(StackTraceElement[] stack, ConsoleTable table) {
		for (StackTraceElement line : stack)
			table.addRowValues("","  at " + line,"","","","");
	}

	private void printThread(Thread thread, ConsoleTable table) {
		ThreadGroup g = thread.getThreadGroup();

		table.addRowValues(
				thread.getId(), 
				thread.getName(), 
				g == null ? "" : g.getName(), 
				thread.getState(),
				thread.getPriority(), 
				thread.isAlive(), 
				thread.isDaemon()
				);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy