Package org.apache.kato.katoview.commands.infocommands

Source Code of org.apache.kato.katoview.commands.infocommands.InfoThreadCommand

/*******************************************************************************
* 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 org.apache.kato.katoview.commands.infocommands;

import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Stack;
import java.util.Iterator;
import java.util.Enumeration;
import java.util.Properties;

import javax.tools.diagnostics.image.CorruptData;
import javax.tools.diagnostics.image.CorruptDataException;
import javax.tools.diagnostics.image.DataUnavailable;
import javax.tools.diagnostics.image.Image;
import javax.tools.diagnostics.image.ImageAddressSpace;
import javax.tools.diagnostics.image.ImageProcess;
import javax.tools.diagnostics.image.ImageRegister;
import javax.tools.diagnostics.image.ImageSection;
import javax.tools.diagnostics.image.ImageStackFrame;
import javax.tools.diagnostics.image.ImageThread;
import javax.tools.diagnostics.image.DiagnosticException;
import javax.tools.diagnostics.runtime.ManagedRuntime;
import javax.tools.diagnostics.runtime.java.JavaLocation;
import javax.tools.diagnostics.runtime.java.JavaMonitor;
import javax.tools.diagnostics.runtime.java.JavaObject;
import javax.tools.diagnostics.runtime.java.JavaRuntime;
import javax.tools.diagnostics.runtime.java.JavaStackFrame;
import javax.tools.diagnostics.runtime.java.JavaThread;

import org.apache.kato.katoview.Output;
import org.apache.kato.katoview.commands.Command;
import org.apache.kato.katoview.commands.helpers.Exceptions;
import org.apache.kato.katoview.commands.helpers.MonitorState;
import org.apache.kato.katoview.commands.helpers.StateToString;
import org.apache.kato.katoview.commands.helpers.ThreadData;
import org.apache.kato.katoview.commands.helpers.Utils;


public class InfoThreadCommand extends Command{
 
  private int pointerSize;
 
  public InfoThreadCommand(Output o){
    super(o, "thread", "displays information about Java and native threads",
        "parameters: none, \"*\", or thread name\n\n" +
        "prints the following information about the current thread, " +
        "all threads, or the specified thread, respectively:\n" +
        " - thread id\n" +
        " - registers\n" +
        " - stack sections\n" +
        " - thread frames: procedure name and base pointer\n" +
        " - the thread properties\n" +
        " - associated Java thread (if applicable):\n" +
        "  - name of Java thread\n" +
        "  - address of associated java.lang.Thread object\n" +
        "  - current state according to JVMTI specification\n" +
        "  - current state relative to java.lang.Thread.State\n" +
        "  - the Java thread priority\n" +
        "  - the monitor the thread is waiting to enter or waiting on notify\n" +
        "  - thread frames: base pointer, method, and filename:line\n"
        );
    child_commands = null;
  }
 
  public void doCommand(Stack args, Image loadedImage, HashMap properties){
    if (args.isEmpty())
    {
      ImageAddressSpace ias = (ImageAddressSpace)properties.get("current_address_space");
      String id;
     
      try {
        ImageThread it = ias.getCurrentProcess().getCurrentThread();
        if (null != it)
          id = it.getID();
        else
        {
          out.print("\n\tNo current (failing) thread, try specifying a native thread ID or '*'\n");
         
          ImageProcess ip = ias.getCurrentProcess();
          if (ip!=null){
            printThreadSummary(ip , out);
          }
         
          return;
        }
      } catch (CorruptDataException e) {
        out.error("exception encountered while getting information about " +
            "current thread");
        return;
      }
      args.push(id);
    }

    String param = (String)args.pop();
   
    if (!args.isEmpty())
    {
      out.error("\"info thread\" takes at most one parameter, which, if " +
          "specified, must be a thread ID or \"*\"");
      return;
    }
   
    if (param.equals("*"))
    {
      out.print("\n");
      printAddressSpaceInfo(loadedImage, out, null, getJavaThreads(loadedImage, null));
      out.print("\n");
    }
    else
    {
      out.print("\n");
      printAddressSpaceInfo(loadedImage, out, param, getJavaThreads(loadedImage, param));
      out.print("\n");
    }
  }
 
  private void printAddressSpaceInfo(Image loadedImage, Output out, String id, Map threads)
  {
    Iterator itAddressSpace;
    ImageAddressSpace ias;
    int asnum = 0;
   
    itAddressSpace = loadedImage.getAddressSpaces().iterator();
    while (itAddressSpace.hasNext()) {
      ias = (ImageAddressSpace)itAddressSpace.next();
      out.print("\n\tnative threads for address space # " + asnum + "\n");
      printProcessInfo(ias, out, id, threads);
      asnum++;
    }
   
    if (!threads.isEmpty()) {
      out.print("\n\tJava threads not associated with known native threads:\n\n");
     
      // retrieve any orphaned Java threads from the hashmap
      ArrayList ta = (ArrayList)threads.remove(null);
      if ( ta != null ) {
        for ( int i=0; i<ta.size(); i++) {
          ThreadData td = (ThreadData)ta.get(i);
          printJavaThreadInfo(out, td.getThread(), getMonitors(td.getRuntime()));
        }
      }
    }
  }
 
  private void printProcessInfo(ImageAddressSpace ias, Output out, String id, Map threads)
  {
    Iterator itProcess;
    ImageProcess ip;
    boolean found = false;
   
    itProcess = ias.getProcesses().iterator();
    while (itProcess.hasNext())
    {
      ip = (ImageProcess)itProcess.next();
      pointerSize = ip.getPointerSize();
     
      out.print("\t process id: ");
      try {
        out.print(ip.getID());
      } catch (DataUnavailable d) {
        out.print(Exceptions.getDataUnavailableString());
      } catch (CorruptDataException e) {
        out.print(Exceptions.getCorruptDataExceptionString());
      }
      out.print("\n\n");
      found = printThreadInfo(ip, out, id, threads);
    }
   
    if (!found)
    {
      out.print("\t no native threads found with specified id\n");
    }
  }
 
  private boolean printThreadInfo(ImageProcess ip, Output out, String id, Map threads)
  {
    Iterator itThread;
    ImageThread it;
    boolean found = false;
   
    itThread = ip.getThreads().iterator();
    while (itThread.hasNext())
    {
      Object next = itThread.next();
      if (next instanceof CorruptData) {
        continue;
      }
      it = (ImageThread)next;
      String currID;
     
      try {
        currID = it.getID();
      } catch (CorruptDataException e) {
        currID = null;
      }
     
      if (null == id || id.equals(currID))
      {
        out.print("\t  thread id: ");
        out.print(currID);
        out.print("\n");
        printRegisters(it);
       
        out.print("\t   stack sections:");
        out.print("\n");
       
        Iterator itStackSection = it.getStackSections().iterator();
        while (itStackSection.hasNext()) {
          Object nextStackSection = itStackSection.next();
          if (nextStackSection instanceof CorruptData) {
            out.print("\t    " + Exceptions.getCorruptDataExceptionString() + "\n");
            continue;
          }
          ImageSection is = (ImageSection)nextStackSection;
          printStackSection(is);
        }
        printStackFrameInfo(it, out);
               
        out.print("\t   properties:");
        out.print("\n");
        printProperties(it, out);
        out.print("\n");
       
        out.print("\t   associated Java thread: ");
        ThreadData td = (ThreadData)threads.remove(currID);
        if (null != td) {
          out.print("\n");
          printJavaThreadInfo(out, td.getThread(), getMonitors(td.getRuntime()));
        } else {
          out.print("<no associated Java thread>\n");
        }
        out.print("\n");
        found = true;
      }
    }
   
    return found;
  }
 
  public void printRegisters(ImageThread it)
  {
    out.print("\t   registers:");
    out.print("\n");
   
    int count = 0;
    Iterator itImageRegister = it.getRegisters().iterator();
    while (itImageRegister.hasNext())
    {
      if (count % 4 == 0)
      {
        if (0 != count)
          out.print("\n");
        out.print("\t    ");
      }
      ImageRegister ir = (ImageRegister)itImageRegister.next();
      printRegisterInfo(ir);
      count++;
    }
    out.print("\n");
  }
 
  public void printRegisterInfo(ImageRegister ir)
  {
    out.print(Utils.padWithSpaces(ir.getName(), 8) + " = ");
    try {
      out.print(toAdjustedHex(ir.getValue().longValue()));
    } catch (CorruptDataException e) {
      out.print(Exceptions.getCorruptDataExceptionString());
    }
    out.print("   ");
  }
 
  public void printStackSection(ImageSection is)
  {
    long startAddr = is.getBaseAddress().getAddress();
    long size = is.getSize();
    long endAddr = startAddr + size;

    out.print("\t    ");
    out.print(Utils.toHex(startAddr));
    out.print(" to ");
    out.print(Utils.toHex(endAddr));
    out.print(" (length ");
    out.print(Utils.toHex(size));
    out.print(")\n");
  }
 
  private void printStackFrameInfo(ImageThread it, Output out)
  {
    Iterator itStackFrame;
    ImageStackFrame isf;
   
    try {
      itStackFrame = it.getStackFrames().iterator();
    } catch (DataUnavailable d) {
      out.print("\t   error with stack frames: " + Exceptions.getDataUnavailableString() + "\n");
      return;
    }
   
    out.print("\t   stack frames:");
    out.print("\n");

    while (itStackFrame.hasNext())
    {
      isf = (ImageStackFrame)itStackFrame.next();
      out.print("\t    bp: ");
      try {
        out.print(toAdjustedHex(isf.getBasePointer().getAddress()));
      } catch (CorruptDataException e) {
        out.print(Exceptions.getCorruptDataExceptionString());
      }
      out.print(" pc: ");
      try {
        out.print(toAdjustedHex(isf.getProcedureAddress().getAddress()));
      } catch (CorruptDataException e) {
        out.print(Exceptions.getCorruptDataExceptionString());
      }
      out.print(" ");
      try {
        out.print(isf.getProcedureName());
      } catch (CorruptDataException e) {
        out.print(Exceptions.getCorruptDataExceptionString());
      }
      out.print("\n");
    }
  }
 
  private Map getJavaThreads(Image loadedImage, String id)
  {
    ManagedRuntime mr;
    Iterator itRuntime = Utils.getRuntimes(loadedImage);
    Map threads = new HashMap();
   
    while (itRuntime.hasNext()) {
      mr = (ManagedRuntime)itRuntime.next();
      if (mr instanceof JavaRuntime)
      {
        JavaRuntime jr = (JavaRuntime)mr;
        Iterator itThread = jr.getThreads().iterator();
       
        while (itThread.hasNext()) {
          JavaThread jt = (JavaThread)itThread.next();
          String currID;

          try {
            ImageThread it = jt.getImageThread()
            currID = it.getID();
          } catch (DiagnosticException e) {
            currID = null;
          }
         
          if (null == id) {
            // thread id set to null means we want all the threads, and we
            // save all orphaned java threads in a list within the hashmap
            if ( null == currID) {
              if (threads.containsKey(null)) {
                ArrayList ta = (ArrayList)threads.get(null);
                ta.add(new ThreadData(jt, jr));
                } else {
                  ArrayList ta = new ArrayList(1);
                  ta.add(new ThreadData(jt, jr));
                  threads.put(null, ta);
                }
            } else {
              threads.put(currID, new ThreadData(jt, jr));
            }
          } else if (id.equals(currID)) {
            // we just want the specific java thread that matches the native one
            threads.put(currID, new ThreadData(jt, jr));
          }
        }
      }
    }
   
    return threads;
  }
 
  private Map getMonitors(JavaRuntime jr)
  {
    Map monitors = new HashMap();
   
    Iterator itMonitor = jr.getMonitors().iterator();
    while (itMonitor.hasNext()) {
      JavaMonitor jm = (JavaMonitor)itMonitor.next();
      Iterator itEnterWaiter = jm.getEnterWaiters().iterator();
      while (itEnterWaiter.hasNext()) {
        JavaThread jt = (JavaThread)itEnterWaiter.next();
        monitors.put(jt, new MonitorState(jm, MonitorState.WAITING_TO_ENTER));
      }
      Iterator itNotifyWaiter = jm.getNotifyWaiters().iterator();
      while (itNotifyWaiter.hasNext()) {
        JavaThread jt = (JavaThread)itNotifyWaiter.next();
        monitors.put(jt, new MonitorState(jm, MonitorState.WAITING_TO_BE_NOTIFIED_ON));
      }
    }
   
    return monitors;
  }
 
  private void printJavaThreadInfo(Output out, JavaThread jt, Map monitors)
  {
    out.print("\t    name:          ");
    try {
      out.print(jt.getName());
    } catch (CorruptDataException e) {
      out.print(Exceptions.getCorruptDataExceptionString());
    }
    out.print("\n");
   
    out.print("\t    Thread object: ");
    try {
      JavaObject threadObj = jt.getObject();
      if (null == threadObj) {
        out.print("<no associated Thread object>");
      } else {
        out.print(Utils.toHex(threadObj.getID().getAddress()));
      }
    } catch (CorruptDataException cde) {
      out.print(Exceptions.getCorruptDataExceptionString());
    }
    out.print("\n");
   
    out.print("\t    JVMTI state:   ");
    try {
      out.print(StateToString.getJVMTIStateString(jt.getState()));
    } catch (CorruptDataException cde) {
      out.print(Exceptions.getCorruptDataExceptionString());
    }
    out.print("\n");

    out.print("\t    Thread.State:  ");
    try {
      out.print(StateToString.getThreadStateString(jt.getState()));
    } catch (CorruptDataException cde) {
      out.print(Exceptions.getCorruptDataExceptionString());
    }
    out.print("\n");
   
    out.print("\t    Priority:      ");
    try {
      Integer pri = new Integer(jt.getPriority());
      out.print(pri.toString());
    } catch (CorruptDataException e) {
      out.print(Exceptions.getCorruptDataExceptionString());
    }
    out.print("\n");
   
    out.print("\t    monitor:       ");
    MonitorState ms = (MonitorState)monitors.get(jt);
    if (null == ms) {
      out.print("<no associated monitor>");
    } else {
      try {
        String name = ms.getMonitor().getName();
        if (name.equals("")) {
          name = "<unnamed>";
        }
        out.print(ms.getStatusString() + " \"" + name + "\"");
      } catch (CorruptDataException cde) {
        out.print(Exceptions.getCorruptDataExceptionString());
      }
      JavaObject jo = ms.getMonitor().getObject();
      if (null == jo) {
        // working with a raw monitor
        out.print(" with ID ");
        // FIXME: once Kato implements IDs, output ID
        out.print("<unavailable>");
      } else {
        // working with a Java monitor
        out.print(" with object ");
        out.print(Utils.toHex(jo.getID().getAddress()));
      }
    }
    out.print("\n");
   
    out.print("\t    thread frames: ");
    printJavaStackFrameInfo(jt, out);
    out.print("\n");
  }
 
  private void printJavaStackFrameInfo(JavaThread jt, Output out)
  {
    Iterator itStackFrame;
    JavaStackFrame jsf;
    JavaLocation jl;

    itStackFrame = jt.getStackFrames().iterator();
    if (!itStackFrame.hasNext()) {
      out.print("<no frames to print>\n");
      return;
    } else {
      out.print("\n");
    }
    while (itStackFrame.hasNext()) {
      // this iterator can contain JavaStackFrame or CorruptData objects
      Object next = itStackFrame.next();
      if (next instanceof CorruptData) {
        out.print("\t     " + Exceptions.getCorruptDataExceptionString() + "\n");
        return;
      } else {
          jsf = (JavaStackFrame)next;
      }
      try {
        jl = jsf.getLocation();
      } catch (CorruptDataException e) {
        out.print("\t     " + Exceptions.getCorruptDataExceptionString()+ "\n");
        return;
      }
     
      out.print("\t     bp: ");
      try {
        out.print(toAdjustedHex(jsf.getBasePointer().getAddress()));
      } catch (CorruptDataException e) {
        out.print(Exceptions.getCorruptDataExceptionString());
      }
     
      out.print("    method: ");
      try {
        String signature = jl.getMethod().getSignature();
        out.print(Utils.getReturnValueName(signature) + " " +
            jl.getMethod().getDeclaringClass().getName() + "." +
            jl.getMethod().getName() +
            Utils.getMethodSignatureName(signature)
            );
      } catch (CorruptDataException e) {
        out.print(Exceptions.getCorruptDataExceptionString());
      } catch (DataUnavailable e) {
        out.print(Exceptions.getDataUnavailableString());
      }

      out.print("    filename:line: ");
      try {
        out.print(jl.getFilename());
      } catch (DataUnavailable d) {
        out.print(Exceptions.getDataUnavailableString());
      } catch (CorruptDataException e) {
        out.print(Exceptions.getCorruptDataExceptionString());
      }
      out.print(":");
      try {
        out.print(Integer.toString(jl.getLineNumber()));
      } catch (DataUnavailable d) {
        out.print(Exceptions.getDataUnavailableString());
      } catch (CorruptDataException e) {
        out.print(Exceptions.getCorruptDataExceptionString());
      }
      out.print("\n");
    }
  }

  private String toAdjustedHex(long l)
  {
    if (pointerSize > 32) {
      return "0x" + Utils.toFixedWidthHex(l);
    } else if (31 == pointerSize) {
      return "0x" + Utils.toFixedWidthHex((int)(l & (((long)1) << pointerSize) - 1));
    } else {
      return "0x" + Utils.toFixedWidthHex((int)l);
    }
  }
 
  private void printThreadSummary(ImageProcess ip, Output out)
  {
    // Prints a summary list of native thread IDs
    int count = 0;
    Iterator itThread = ip.getThreads().iterator();
     
    while (itThread.hasNext()) {
      Object next = itThread.next();
      if (next instanceof CorruptData)
            continue;
      ImageThread it = (ImageThread)next;
     
      if (count % 8 == 0) {
        if (0 == count)
          out.print("\n\n\tNative thread IDs for current process:");
        out.print("\n\t ");
      }
     
      try {
        out.print(Utils.padWithSpaces(it.getID(), 8));
      } catch (CorruptDataException e) {
        out.print(Exceptions.getCorruptDataExceptionString());
      }
      count++;
    }
    out.print("\n");
  }
  private void printProperties(ImageThread it, Output out)
  {
    Properties jtp = it.getProperties();
    Enumeration keys = jtp.propertyNames();
    while (keys.hasMoreElements())
    {
      String propertyKey = keys.nextElement().toString();
      out.print("\t    " + propertyKey + ": " + jtp.getProperty(propertyKey));
      out.print("\n");
    }
  }
}
TOP

Related Classes of org.apache.kato.katoview.commands.infocommands.InfoThreadCommand

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.