Package org.apache.kato.katoview.commands

Source Code of org.apache.kato.katoview.commands.HeapdumpCommand

/*******************************************************************************
* 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;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

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.DiagnosticException;
import javax.tools.diagnostics.image.MemoryAccessException;
import javax.tools.diagnostics.runtime.java.JavaClass;
import javax.tools.diagnostics.runtime.java.JavaClassLoader;
import javax.tools.diagnostics.runtime.java.JavaField;
import javax.tools.diagnostics.runtime.java.JavaHeap;
import javax.tools.diagnostics.runtime.java.JavaObject;
import javax.tools.diagnostics.runtime.java.JavaRuntime;

import org.apache.kato.katoview.Output;
import org.apache.kato.katoview.heapdump.HeapDumpFormatter;
import org.apache.kato.katoview.heapdump.HeapDumpSettings;
import org.apache.kato.katoview.heapdump.LongListReferenceIterator;
import org.apache.kato.katoview.heapdump.ReferenceIterator;
import org.apache.kato.katoview.heapdump.classic.ClassicHeapDumpFormatter;


/**
* Command for dumping heapdumps from Kato.
*
* Contains the heap-walking logic for building the reference tree.
*
*/
public class HeapdumpCommand extends Command
{
  public static final String COMMAND_NAME = "heapdump";
  public static final String DESCRIPTION = "generates a heapdump";
  public static final String LONG_DESCRIPTION = "Parameters: [heapname+]\n\n"
      + "\t[heapname+] - space-separated name of heap or heaps to dump. Use \"info heap\" to get the list of heap names. Default: all heaps are dumped.\n\n"
      + "Writes a heapdump from the memory image.\n"
      + "The file name and format are controlled using the \"set heapdump\" command; the current settings "
      + "can be displayed using \"show heapdump\".\n";
   
  private static final String PROTECTION_DOMAIN_FIELD_NAME = "protectionDomain";
  /**
   * Regexp pattern used to extract a subset of the versions string
   */
  private static final Pattern J9_VERSION_PATTERN = Pattern.compile("(IBM J9 VM.*?\\))");
  //Do not change the order this array - the indexes are used to extract type codes in the getPrimitiveTypeCode method
  private static final String[] PRIMITIVE_TYPES = { "boolean", "char",
      "float", "double", "byte", "short", "int", "long", "void" };
  private int _numberOfObjects = 0;
  private int _numberOfClasses = 0;
  private int _numberOfErrors = 0;
  private boolean _verbose = false;

  public HeapdumpCommand(Output o)
  {
    super(o, COMMAND_NAME, DESCRIPTION, LONG_DESCRIPTION);
    child_commands = null;
  }

  public void doCommand(Stack args, Image loadedImage, HashMap properties)
  {
    Set heapsToDump = new HashSet();
   
    while(! args.isEmpty()) {
      heapsToDump.add(args.pop());
    }

    _numberOfObjects = 0;
    _numberOfErrors = 0;
    _numberOfClasses = 0;
   
    Object verboseModeStr = properties.get("verbose.mode");
    _verbose = verboseModeStr != null ? verboseModeStr.equals("on") : false;
   
    ImageAddressSpace addressSpace = (ImageAddressSpace) properties.get("current_address_space");
   
    if(addressSpace == null) {
      out.error("Couldn't get handle on address space");
      return;
    }

    JavaRuntime runtime = getRuntime(addressSpace);
   
    if(runtime == null) {
      return;
    }
   
    if(! heapArgumentsAreValid(runtime,heapsToDump)) {
      return;
    }

    String version = getVersionString(runtime);

    boolean is64Bit = addressSpace.getCurrentProcess().getPointerSize() == 64;
    String filename = HeapDumpSettings.getFileName(properties);
    boolean phdFormat = HeapDumpSettings.areHeapDumpsPHD(properties);
   
    try {
      if(HeapDumpSettings.multipleHeapsInMultipleFiles(properties)) {
        dumpMultipleHeapsInSeparateFiles(runtime,version,is64Bit,phdFormat,filename,heapsToDump);
      } else {
        dumpMultipleHeapsInOneFile(runtime,version,is64Bit,phdFormat,filename,heapsToDump);
      }
     
      if(_numberOfErrors == 0) {
        out.print("\nSuccessfully wrote " + _numberOfObjects + " objects and " + _numberOfClasses + " classes\n");
      } else {
        out.print("\nWrote "
            + _numberOfObjects
            + " objects and "
            + _numberOfClasses
            + " classes and encountered "
            + _numberOfErrors
            + " errors."
            + (! _verbose ? " Start KatoView with -verbose for more detail." : "")
            + "\n");
      }
    }
    catch (IOException ex) {
      out.error("I/O error writing dump:\n");
      StringWriter writer = new StringWriter();
      ex.printStackTrace(new PrintWriter(writer));
      out.error(writer.toString());
    }
  }
 
  /**
   * Checks the list of heaps to dump as specified by the user.
   * @param runtime Current java runtime
   * @param heapsToDump Set of strings the user passed as heaps to dump
   * @return True if all the names are valid heaps, false otherwise
   */
  private boolean heapArgumentsAreValid(JavaRuntime runtime, Set heapsToDump)
  {
    if(heapsToDump.size() == 0) {
      return true;
    }
   
    Set workingSet = new HashSet();
    workingSet.addAll(heapsToDump);
   
    Iterator heapIt = runtime.getHeaps().iterator();
   
    while(heapIt.hasNext()) {
      Object potential = heapIt.next();
     
      if(potential instanceof JavaHeap) {
        JavaHeap thisHeap = (JavaHeap)potential;
       
        workingSet.remove(thisHeap.getName());
      } else if (potential instanceof CorruptData) {
        reportError("Corrupt heap found. Address = " + ((CorruptData)potential).getAddress(),null);
        _numberOfErrors++;
      } else {
        _numberOfErrors++;
        reportError("Unexpected type " + potential.getClass().getName() + " found in heap iterator",null);
      }
    }
   
    if(workingSet.isEmpty()) {
      return true;
    } else {
      StringBuffer buffer = new StringBuffer();
      buffer.append("These specified heaps do not exist:\n");
     
      Iterator nameIterator = workingSet.iterator();
     
      while(nameIterator.hasNext()) {
        buffer.append("\t\t" + nameIterator.next() + "\n");
      }
     
      buffer.append("\tUse \"info heap\" to see list of heap names");
     
      out.error(buffer.toString());
     
      return false;
    }
  }

  /**
   * Extracts a minimal version string from the full -version output
   */
  private String getVersionString(JavaRuntime runtime)
  {
    try {
      String rawVersion = runtime.getVersion();
     
      Matcher matcher = J9_VERSION_PATTERN.matcher(rawVersion);
     
      if(matcher.find()) {
        String minimalVersion = matcher.group(1);
        return minimalVersion;
      } else {
        _numberOfErrors++;
        reportError("Could not parse version string: " + rawVersion,null);
        return rawVersion;
      }
    }
    catch (CorruptDataException e) {
      _numberOfErrors++;
      out.error("Could not read version string from dump: data corrupted at "
              + e.getCorruptData().getAddress());
      return "*Corrupt*";
    }
  }
 
  private JavaRuntime getRuntime(ImageAddressSpace addressSpace)
  {
    ImageProcess process = addressSpace.getCurrentProcess();
   
    if(process == null) {
      out.error("Couldn't get handle on current process");
      return null;
    }
   
    Iterator runtimeIterator = process.getRuntimes().iterator();
   
    if(! runtimeIterator.hasNext()) {
      out.error("Cannot find a runtime");
      return null;
    }
   
    Object potential = runtimeIterator.next();
   
    if(potential instanceof CorruptData) {
      out.error("Runtime data is corrupt");
      return null;
    }
   
    return (JavaRuntime) potential;
  }

  private void dumpMultipleHeapsInOneFile(JavaRuntime runtime,
      String version, boolean is64Bit, boolean phdFormat, String filename, Set heapsToDump) throws IOException
  {
    Iterator heapIterator = runtime.getHeaps().iterator();
   
    HeapDumpFormatter formatter = getFormatter(filename, version, is64Bit, phdFormat);
   
    out.print("Writing " + ( phdFormat ? "PHD" : "Classic") + " format heapdump into " + filename);
   
    dumpClasses(formatter,runtime);
   
    while (heapIterator.hasNext()) {
      Object thisHeapObj = heapIterator.next();

      if (thisHeapObj instanceof CorruptData) {
        out.error("Corrupt heap data found at: "
            + ((CorruptData) thisHeapObj).getAddress());
        _numberOfErrors++;
        continue;
      }

      JavaHeap thisHeap = (JavaHeap) thisHeapObj;
     
      if(heapsToDump.size() > 0 && ! heapsToDump.contains(thisHeap.getName())) {
        continue;
      }
     
      dumpHeap(formatter, thisHeap);
    }
   
    formatter.close();
  }

  private void dumpMultipleHeapsInSeparateFiles(JavaRuntime runtime,String version, boolean is64Bit, boolean phdFormat,String baseFileName, Set heapsToDump) throws IOException
  {
    Iterator heapIterator = runtime.getHeaps().iterator();
   
    HeapDumpFormatter formatter = null;
   
    while (heapIterator.hasNext()) {
      Object thisHeapObj = heapIterator.next();

      if (thisHeapObj instanceof CorruptData) {
        out.error("Heap corrupted at: "
            + ((CorruptData) thisHeapObj).getAddress());
        _numberOfErrors++;
        continue;
      }

      JavaHeap thisHeap = (JavaHeap) thisHeapObj;

      // Create a new heapdump formatter for every heap we find
      if (formatter != null) {
        formatter.close();
      }

      if(heapsToDump.size() > 0 && ! heapsToDump.contains(thisHeap.getName())) {
        continue;
      }
     
      String fileName = getFileNameForHeap(thisHeap,baseFileName);

      out.print("Writing "
          + ( phdFormat ? "PHD" : "Classic")
          + " format heapdump for heap "
          + thisHeap.getName()
          + " into "
          + fileName + "\n");
     
      formatter = getFormatter(fileName, version, is64Bit, phdFormat);
     
      //We have to dump classes in every heapdump
      dumpClasses(formatter,runtime);
     
      dumpHeap(formatter, thisHeap);
    }
   
    if(formatter != null) {
      formatter.close();
    }
  }

  /**
   * Walks the runtime classes and passes them through the formatter interface
   */
  private void dumpClasses(HeapDumpFormatter formatter, JavaRuntime runtime) throws IOException
  {
    Iterator classLoaderIt = runtime.getJavaClassLoaders().iterator();
   
    int numberOfClasses = 0;
   
ITERATING_LOADERS:while(classLoaderIt.hasNext()) {
      Object potential = classLoaderIt.next();
     
      if(potential instanceof CorruptData) {
        _numberOfErrors++;
        reportError("CorruptData found in classloader list at address: " + ((CorruptData)potential).getAddress(), null);
        continue ITERATING_LOADERS;
      }
     
      JavaClassLoader thisClassLoader = (JavaClassLoader)potential;
     
      Iterator classesIt = thisClassLoader.getDefinedClasses().iterator();
     
ITERATING_CLASSES:while(classesIt.hasNext()) {
        potential = classesIt.next();
       
        numberOfClasses++;
       
        try {
         
          if(potential instanceof CorruptData) {
            _numberOfErrors++;
            reportError("CorruptData found in class list for classloader "
                + Long.toHexString(thisClassLoader.getObject().getID().getAddress())
                + " at address: " + ((CorruptData)potential).getAddress(), null);
            continue ITERATING_CLASSES;
          }

          JavaClass thisJavaClass = (JavaClass)potential;
         
          JavaClass superClass = thisJavaClass.getSuperclass();
         
          JavaObject classObject = thisJavaClass.getObject();
         
          int instanceSize = 0;

          if(thisJavaClass.isArray()) {
            instanceSize = 0;
          } else {
            // we need to figure out a way of determining the instance size for a class
          }
         
          formatter.addClass(thisJavaClass.getID().getAddress(),
                thisJavaClass.getName(),
                superClass != null ? superClass.getID().getAddress() : 0,
                classObject != null ? (int)classObject.getSize() : 0,
                instanceSize,
                classObject != null ? (int)classObject.getPersistentHashcode() : 0,
                getClassReferences(thisJavaClass) );
        } catch(DiagnosticException ex) {
          //Handle CorruptDataException and DataUnavailableException the same way
          _numberOfErrors++;
          reportError(null,ex);
          continue ITERATING_CLASSES;
        }
      }
    }
   
     _numberOfClasses = numberOfClasses;
  }

  /**
   * Walks the supplied heap and passes the artifacts through the formatter
   */
  private void dumpHeap(HeapDumpFormatter formatter, JavaHeap thisHeap)
      throws IOException
  {
    Iterator objectIterator = thisHeap.getObjects().iterator();

    while (objectIterator.hasNext()) {
      Object next = objectIterator.next();
      _numberOfObjects++;

      if (next instanceof CorruptData) {
        _numberOfErrors++;
        reportError("Corrupt object data found at " + ((CorruptData)next).getAddress() + " while walking heap " + thisHeap.getName(),null);
        continue;
      }

      try {
        JavaObject thisObject = (JavaObject) next;
        JavaClass thisClass = thisObject.getJavaClass();

        int hashcode = 0;

        try {
          hashcode = (int) thisObject.getHashcode();
        }
        catch (DataUnavailable ex) {
          _numberOfErrors++;
          reportError("Failed to get hashcode for object: " + thisObject.getID(),ex);
        }

        if (thisObject.isArray()) {
          if (isPrimitive(thisClass.getComponentType())) {
            formatter.addPrimitiveArray(thisObject.getID().getAddress(),
                          thisClass.getID().getAddress(),
                          getPrimitiveTypeCode(thisClass.getComponentType()),
                          (int) thisObject.getSize(),
                          hashcode,
                          thisObject.getArraySize());
          }
          else {
           
            formatter.addObjectArray(thisObject.getID().getAddress(),
                thisClass.getID().getAddress(),
                thisClass.getName(),
                thisClass.getComponentType().getID().getAddress(),
                thisClass.getComponentType().getName(),
                (int) thisObject.getSize(),
                thisObject.getArraySize(),
                hashcode,
                getObjectReferences(thisObject));
          }
        }
        else {
          formatter.addObject(thisObject.getID().getAddress(),
                    thisClass.getID().getAddress(),
                    thisClass.getName(),
                    (int)thisObject.getSize(),
                    hashcode,
                    getObjectReferences(thisObject));
        }
      }
      catch (CorruptDataException ex) {
        _numberOfErrors++;
        reportError(null,ex);
        continue;
      }
    }
  }

  /* Reference code reimplemented (rather than using the Kato getReferences() API)
   * because we are trying to match the behaviour of the runtime heapdump rather than
   * the GC spec. The set of references we're trying to create is different.
   */

  /**
   * Gets the references for the supplied class
   *
   * @param thisJavaClass Class being examined
   */
  private ReferenceIterator getClassReferences(JavaClass thisJavaClass)
  {
    List references = new LinkedList();
   
    try {
      //Statics       
      addStaticReferences(thisJavaClass, references);
     
      addProtectionDomainReference(thisJavaClass,references);
     
      //Classloader
      JavaClassLoader loader = thisJavaClass.getClassLoader();
     
      if(loader != null) {
        JavaObject loaderObject = loader.getObject();
        if(loaderObject != null) {
          references.add(new Long(loaderObject.getID().getAddress()));
        } else {
          reportError("Null loader object returned for class: " + thisJavaClass.getName() + "(" + thisJavaClass.getID() + ")",null);
          _numberOfErrors++;
        }
      } else {
        reportError("Null classloader returned for class: " + thisJavaClass.getName() + "(" + thisJavaClass.getID() + ")",null);
        _numberOfErrors++;
      }
   
      //Heap object
      JavaObject classObject = thisJavaClass.getObject();
      if(classObject != null) {
        references.add(new Long(classObject.getID().getAddress()));
      } else {
        _numberOfErrors++;
        reportError("Couldn't get Java class loader for: " + thisJavaClass.getName() + "(" + thisJavaClass.getID() + ")",null);
      }
     
    } catch(DiagnosticException ex) {
      reportError(null,ex);
      _numberOfErrors++;
    }
   
    return new LongListReferenceIterator(references);
  }
 
  private JavaField _protectionDomainField;
 
  private void addProtectionDomainReference(JavaClass thisJavaClass,
      List references) throws CorruptDataException, MemoryAccessException
     
  {
    JavaObject classObject = thisJavaClass.getObject();
   
    //Protection domain hangs off the protectionDomain field on the class object
    if(_protectionDomainField == null) {
      JavaClass javaLangClassObject = classObject.getJavaClass();
      if(javaLangClassObject == null) {
        _numberOfErrors++;
        reportError("Couldn't find java.lang.Class class",null);
        return;
      }
      Iterator fieldsIt = javaLangClassObject.getDeclaredFields().iterator();
     
      while(fieldsIt.hasNext()) {
        Object potential = fieldsIt.next();
       
        if(potential instanceof JavaField) {
          JavaField field = (JavaField) potential;
         
          if(field.getName().equals(PROTECTION_DOMAIN_FIELD_NAME)) {
            _protectionDomainField = field;
          }
        } else if(potential instanceof CorruptData) {
          _numberOfErrors++;
          reportError("CorruptData found walking fields for java.lang.Class. Bad address = "
              + ((CorruptData)potential).getAddress()
              ,null);
        } else {
          _numberOfErrors++;
          reportError("Unexpected type "
              + potential.getClass()
              + " returned from fields iterator."
              ,null);
        }
      }
     
      if(_protectionDomainField == null) {
        _numberOfErrors++;
        reportError("Couldn't find protection domain field.",null);
        return;
      }
    }
   
    Object potential = _protectionDomainField.get(classObject);
   
    if(potential instanceof JavaObject) {
      JavaObject protectionDomain = (JavaObject)potential;
     
      references.add(new Long(protectionDomain.getID().getAddress()));
    } else if (potential instanceof CorruptData) {
      _numberOfErrors++;
      reportError("Corrupt data found in protectionDomainField of "
          + thisJavaClass.getName()
          + " at address "
          + ((CorruptData)potential).getAddress()
          ,null);
    } else if (potential == null) {
      //Do nothing
    } else {
      reportError("Unexpected type: "
          + potential.getClass().getName()
          + " found in protectionDomain field of "
          + thisJavaClass.getName()
          ,null);
      _numberOfErrors++;
    }
  }

  /**
   * Extracts static references from class
   * @param thisClass Class being examined
   * @param references List to add references to
   */
  private void addStaticReferences(JavaClass thisClass, List references)
      throws CorruptDataException, MemoryAccessException
  {
    Iterator fieldsIt = thisClass.getDeclaredFields().iterator();
     
    while(fieldsIt.hasNext()) {
      Object potential = fieldsIt.next();
       
      if(potential instanceof CorruptData) {
        reportError("Corrupt field found in class "
            + thisClass.getName()
            + "(" + thisClass.getID() + ") at "
            + ((CorruptData)potential).getAddress()
            ,null);
        _numberOfErrors++;
        continue;
      }
       
      JavaField field = (JavaField) potential;
       
      if(! Modifier.isStatic(field.getModifiers())) {
        continue;
      }
       
      Object referent = field.get(thisClass.getObject());
         
      if(referent instanceof CorruptData) {
        _numberOfErrors++;
        reportError("Corrupt referent found in class "
            + thisClass.getName()
            + "(" + thisClass.getID() + ") from field "
            + field.getName()
            + " at address "
            + ((CorruptData)potential).getAddress()
            ,null);
      } else if (referent instanceof JavaObject) {
        JavaObject referredObject = (JavaObject) referent;
         
        references.add(new Long(referredObject.getID().getAddress()));
      } else if (referent == null) {
        references.add(new Long(0));
      } else if (referent instanceof Number || referent instanceof Boolean || referent instanceof Character) {
        //Ignore
      } else {
        reportError("Unexpected type: "
            + referent.getClass().getName()
            + " returned from field "
            + field.getName()
            + " from class "
            + thisClass.getName()
            + "(" + thisClass.getID()+ ")"
            ,null);
        _numberOfErrors++;
      }
    }
  }
 
  /**
   * Gets instance references for objects
   * @param thisObject Object being examined
   * @return Iterator of references
   */
  private ReferenceIterator getObjectReferences(JavaObject thisObject)
  {
    List references = new LinkedList();
   
    try {
      JavaClass thisClass = thisObject.getJavaClass();
   
      if(thisClass.isArray()) {
        addArrayReferences(thisObject, references);
      } else {
        addRegularObjectReferences(thisObject, references,thisClass);
      }
    } catch(DiagnosticException ex) {
      _numberOfErrors++;
      reportError(null,ex);
    }
   
    return new LongListReferenceIterator(references);
  }

  /**
   * Extracts the instance references from object arrays
   * @param arrayObject Array
   * @param references List to add references to
   */
  private void addArrayReferences(JavaObject arrayObject, List references)
      throws CorruptDataException, MemoryAccessException
  {
    JavaObject[] localArray = new JavaObject[arrayObject.getArraySize()];
    arrayObject.arraycopy(0, localArray, 0, arrayObject.getArraySize());
   
    for(int i=0;i!=localArray.length;i++) {
      if(localArray[i] != null) {
        references.add(new Long(localArray[i].getID().getAddress()));
      } else {
        references.add(new Long(0));
      }
    }
  }

  /**
   * Extracts the instance references from a regular (non-array) object
   * @param object Object being walked
   * @param references List to add references to
   * @param thisClass Class of object
   */
  private void addRegularObjectReferences(JavaObject object,
      List references, JavaClass thisClass) throws CorruptDataException,
      MemoryAccessException
  {
    while(thisClass != null) {
     
      Iterator fieldsIt = thisClass.getDeclaredFields().iterator();
     
WALKING_FIELDS: while(fieldsIt.hasNext()) {
        Object potential = fieldsIt.next();
       
        if(potential instanceof CorruptData) {
          _numberOfErrors++;
          reportError("Corrupt data found at address "
              + ((CorruptData)potential).getAddress()
              + " walking fields of class: "
              + thisClass.getName()
              + "(" + thisClass.getID() + ")"
              ,null);
          continue WALKING_FIELDS;
        }
       
        JavaField field = (JavaField) potential;
       
        if(Modifier.isStatic(field.getModifiers())) {
          continue WALKING_FIELDS;
        }
       
        Object referent = field.get(object);
         
        if(referent instanceof CorruptData) {
          _numberOfErrors++;
          reportError("Corrupt data found in referent at address "
              + ((CorruptData)referent).getAddress()
              + " walking field "
              + field.getName()
              + " of class: "
              + thisClass.getName()
              + "(" + thisClass.getID() + ")"
              ,null);
          continue WALKING_FIELDS;
        } else if (referent instanceof JavaObject) {
          JavaObject referredObject = (JavaObject) referent;
         
          references.add(new Long(referredObject.getID().getAddress()));
        } else if (referent == null) {
          references.add(new Long(0));
        } else if (referent instanceof Number || referent instanceof Boolean || referent instanceof Character) {
            //Ignore
        } else {
          reportError("Unexpected type: " + referent.getClass().getName() + " found in referent",null);
          _numberOfErrors++;
        }
      }
     
      thisClass = thisClass.getSuperclass();
    }
  }

  /**
   * Checks if class is primitive
   *
   * @param clazz
   *            Class under test
   * @return True if clazz represents a primitive type, false otherwise
   */
  private static boolean isPrimitive(JavaClass clazz)
      throws CorruptDataException
  {
    String name = clazz.getName();

    /* Fastpath, anything containing a / cannot be primitive */
    if (name.indexOf("/") != -1) {
      return false;
    }

    for (int i = 0; i != PRIMITIVE_TYPES.length; i++) {
      if (PRIMITIVE_TYPES[i].equals(name)) {
        return true;
      }
    }

    return false;
  }

  /**
   * Converts a class into a primitive type code (as used by the HeapdumpFormatter interface).
   * @param clazz
   * @return
   */
  private int getPrimitiveTypeCode(JavaClass clazz)
      throws CorruptDataException
  {
    String name = clazz.getName();

    for (int i = 0; i != PRIMITIVE_TYPES.length; i++) {
      if (PRIMITIVE_TYPES[i].equals(name)) {
        return i;
      }
    }

    throw new IllegalArgumentException("Class: " + name
        + " is not primitive");
  }

  /**
   * Factory method for HeapDumpFormatters
   * @param fileName File name for output file
   * @param version Version string
   * @param is64Bit True if 64 bit
   * @param phdFormat True if using PhD format
   */
  private HeapDumpFormatter getFormatter(String fileName, String version,
      boolean is64Bit, boolean phdFormat) throws IOException
  {
    return new ClassicHeapDumpFormatter(new FileWriter(fileName),version,is64Bit);
  }

  /**
   * Modifies the base file name to include the heap name, whilst maintaining
   * the suffix
   */
  private String getFileNameForHeap(JavaHeap thisHeap, String baseFileName)
  {
    int pointIndex = baseFileName.lastIndexOf(".");
   
    if(pointIndex != -1) {
      return baseFileName.substring(0,pointIndex) + "." + thisHeap.getName() + baseFileName.substring(pointIndex);
    } else {
      return baseFileName + "." + thisHeap.getName();
    }
  }

  /**
   * Internal error handling routine that only reports the supplied message if verbose was supplied on the command line.
   */
  private void reportError(String msg,Throwable t)
  {
    //Property set in Session.imageFromCommandLine when -verbose specified on command line
    if(!_verbose) {
      return;
    }
   
    if(msg != null) {
      out.error(msg);
    }
   
    if(t != null) {
      StringWriter writer = new StringWriter();
     
      t.printStackTrace(new PrintWriter(writer));
     
      out.error(writer.toString());
    }
  }
}
TOP

Related Classes of org.apache.kato.katoview.commands.HeapdumpCommand

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.