From kato-commits-return-28-apmail-incubator-kato-commits-archive=incubator.apache.org@incubator.apache.org Mon Mar 16 17:05:25 2009 Return-Path: Delivered-To: apmail-incubator-kato-commits-archive@minotaur.apache.org Received: (qmail 32432 invoked from network); 16 Mar 2009 17:05:25 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 16 Mar 2009 17:05:25 -0000 Received: (qmail 22746 invoked by uid 500); 16 Mar 2009 17:05:25 -0000 Delivered-To: apmail-incubator-kato-commits-archive@incubator.apache.org Received: (qmail 22732 invoked by uid 500); 16 Mar 2009 17:05:25 -0000 Mailing-List: contact kato-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: kato-dev@incubator.apache.org Delivered-To: mailing list kato-commits@incubator.apache.org Delivered-To: moderator for kato-commits@incubator.apache.org Received: (qmail 84670 invoked by uid 99); 16 Mar 2009 16:43:33 -0000 X-ASF-Spam-Status: No, hits=-1999.3 required=10.0 tests=ALL_TRUSTED,FRT_LEVITRA X-Spam-Check-By: apache.org Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r754946 [2/3] - in /incubator/kato/trunk/import/org.apache.kato.tools.jdi: ./ .settings/ META-INF/ lib/ src/ src/com/ src/com/ibm/ src/com/ibm/tools/ src/com/ibm/tools/jdi/ Date: Mon, 16 Mar 2009 16:42:52 -0000 To: kato-commits@incubator.apache.org From: ccristal@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090316164253.10FC92388CC0@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: incubator/kato/trunk/import/org.apache.kato.tools.jdi/src/com/ibm/tools/jdi/DTFJReader.java URL: http://svn.apache.org/viewvc/incubator/kato/trunk/import/org.apache.kato.tools.jdi/src/com/ibm/tools/jdi/DTFJReader.java?rev=754946&view=auto ============================================================================== --- incubator/kato/trunk/import/org.apache.kato.tools.jdi/src/com/ibm/tools/jdi/DTFJReader.java (added) +++ incubator/kato/trunk/import/org.apache.kato.tools.jdi/src/com/ibm/tools/jdi/DTFJReader.java Mon Mar 16 16:42:51 2009 @@ -0,0 +1,2752 @@ +/******************************************************************************* + * 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 com.ibm.tools.jdi; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.lang.reflect.Modifier; +import java.net.InetAddress; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Vector; + +import com.ibm.dtfj.image.CorruptData; +import com.ibm.dtfj.image.CorruptDataException; +import com.ibm.dtfj.image.DataUnavailable; +import com.ibm.dtfj.image.Image; +import com.ibm.dtfj.image.ImageAddressSpace; +import com.ibm.dtfj.image.ImageFactory; +import com.ibm.dtfj.image.ImageProcess; +import com.ibm.dtfj.java.JavaClass; +import com.ibm.dtfj.java.JavaClassLoader; +import com.ibm.dtfj.java.JavaField; +import com.ibm.dtfj.java.JavaHeap; +import com.ibm.dtfj.java.JavaLocation; +import com.ibm.dtfj.java.JavaMethod; +import com.ibm.dtfj.java.JavaObject; +import com.ibm.dtfj.java.JavaRuntime; +import com.ibm.dtfj.java.JavaStackFrame; +import com.ibm.dtfj.java.JavaThread; + +/** + * DTFJReader + * + * DTFJReader is our second conversion layer (after JDWPServer). DTFJReader has two functions: + *
    + *
  1. Convert JDWP <--> DTFJ
  2. + *
  3. Provide several convenience methods
  4. + *
+ * + *
    + *
  1. + *

    + * DTFJReader directly takes the raw protocol (in it's object version) and runs some calls to + * get the JDWP reply. Only a small portion of the JDWP protocol is specified in a way that + * we can reliably create objects, so a lot of time the DTFJReader methods will extract their + * own information from a raw byte 'data' segment of the original packet. On the reply, we + * copy some of the information from the CommandPacket (such as sequence and origin socket) + * and then create a data segment. + *

    + *
    + *

    + * Most of the time the data segment is constructed using a Byte vector (that's Big Byte). + * We do this so that we can easily add and remove to the vector, and add to the front if + * we need to. The JDWPServer converts the standard Packet stuff back to bytes and appends + * our data segment on the outgoing packet. + *

    + *
  2. + *
  3. + * We provide bytes <--> int, bytes <--> long, vector --> byte[], and a few other assorted + * methods for doing standard stuff. + *
  4. + *
+ * + */ +public class DTFJReader implements CacherProvider{ + private HashMap classes; + // Image is actually an 'image' of the core at crash time. + // Since it's the basis of every query, I'm saving it over queries + private Image image = null; + private HashMap vctrs; + private String pathToCore; + private int errorCode; + private JDWPServer svr; + + public static final int FLAG_REPLY_PACKET = 0x80; + + private int LAST_ID = 1; + private HashMap intToMethod; + private HashMap methodToInt; + private Vector fieldList; + private JDILogger logr; + public static final int ERROR_NONE = 0; + public static final int ERROR_INVALID_OBJECT = 20; + public static final int ERROR_INVALID_THREAD = 10; + public static final int ERROR_NOT_IMPLEMENTED = 99; + public static final int ERROR_ABSENT_INFORMATION = 101; + public static final int ERROR_INTERNAL = 113; + public static final int ERROR_INVALID_ARRAY = 508; + private HashMap objectMap; + + public static final int COMMANDSET_VIRTUAL_MACHINE = 1; + public static final int COMMANDSET_REFERENCE_TYPE = 2; + public static final int COMMANDSET_CLASS_TYPE = 3; + public static final int COMMANDSET_ARRAY_TYPE = 4; + public static final int COMMANDSET_INTERFACE_TYPE = 5; + public static final int COMMANDSET_METHOD = 6; + + public static final int COMMANDSET_FIELD = 8; + public static final int COMMANDSET_OBJECT_REFERENCE = 9; + public static final int COMMANDSET_STRING_REFERENCE = 10; + public static final int COMMANDSET_THREAD_REFERENCE = 11; + public static final int COMMANDSET_THREAD_GROUP_REFERENCE = 12; + public static final int COMMANDSET_ARRAY_REFERENCE = 13; + public static final int COMMANDSET_CLASS_LOADER_REFERENCE = 14; + public static final int COMMANDSET_EVENT_REQUEST = 15; + public static final int COMMANDSET_STACK_FRAME = 16; + public static final int COMMANDSET_CLASS_OBJECT_REFERENCE = 17; + public static final int COMMANDSET_EVENT = 64; + + public static final int VIRTUAL_MACHINE_VERSION = 1; + public static final int VIRTUAL_MACHINE_CLASSES_BY_SIGNATURE = 2; + public static final int VIRTUAL_MACHINE_ALL_CLASSES = 3; + public static final int VIRTUAL_MACHINE_ALL_THREADS = 4; + public static final int VIRTUAL_MACHINE_TOP_LEVEL_THREAD_GROUPS = 5; + public static final int VIRTUAL_MACHINE_DISPOSE = 6; + public static final int VIRTUAL_MACHINE_IDSIZES = 7; + public static final int VIRTUAL_MACHINE_SUSPEND = 8; + public static final int VIRTUAL_MACHINE_RESUME = 9; + public static final int VIRTUAL_MACHINE_EXIT = 10; + public static final int VIRTUAL_MACHINE_CREATE_STRING = 11; + public static final int VIRTUAL_MACHINE_CAPABILITIES = 12; + public static final int VIRTUAL_MACHINE_CLASS_PATHS = 13; + public static final int VIRTUAL_MACHINE_DISPOSE_OBJECTS = 14; + public static final int VIRTUAL_MACHINE_HOLD_EVENTS = 15; + public static final int VIRTUAL_MACHINE_RELEASE_EVENTS = 16; + public static final int VIRTUAL_MACHINE_CAPABILITIES_NEW = 17; + public static final int VIRTUAL_MACHINE_REDEFINE_CLASSES = 18; + public static final int VIRTUAL_MACHINE_SET_DEFAULT_STRATUM = 19; + + public static final int REFERENCE_TYPE_SIGNATURE = 1; + public static final int REFERENCE_TYPE_CLASS_LOADER = 2; + public static final int REFERENCE_TYPE_MODIFIERS = 3; + public static final int REFERENCE_TYPE_FIELDS = 4; + public static final int REFERENCE_TYPE_METHODS = 5; + public static final int REFERENCE_TYPE_GET_VALUES = 6; + public static final int REFERENCE_TYPE_SOURCE_FILE = 7; + public static final int REFERENCE_TYPE_NESTED_TYPES = 8; + public static final int REFERENCE_TYPE_STATUS = 9; + public static final int REFERENCE_TYPE_INTERFACES = 10; + public static final int REFERENCE_TYPE_CLASS_OBJECT = 11; + public static final int REFERENCE_TYPE_SOURCE_DEBUG_EXTENSION = 12; + + + + + public DTFJReader(){ + + } + + /** + * Constructor to init DTFJ reader + * + * @param ipathToCore Path to core (absolute or relative) + * @param isvr JDWPServer used for communication back up + * @param logger JDILogger to use to log against + * @throws Exception An error passed up from the DTFJ api, or sanity test fail + */ + public DTFJReader(String ipathToCore, JDWPServer isvr, JDILogger logger) throws Exception{ + logr = logger; + logr.log(JDILogger.LEVEL_VERYVERBOSE, "DTFJReader 1.0"); //$NON-NLS-1$ + pathToCore = ipathToCore; + svr = isvr; + vctrs = new HashMap(); + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Starting to read core file"); //$NON-NLS-1$ + startRead(); + + } + + /** + * Given a DTFJ JavaField and JavaObject, add the tagged value to the vector vctr + * + * @param vctr Current byte vector for the data segment of the packet + * @param jObject Object to which get the value from + * @param jField The field of a class to get the value from + * @return false if the operation failed, true if it succeeds + * @throws Exception Exception passed up if underlying DTFJ calls fail + */ + + private boolean getValueFromField(Vector vctr, JavaObject jObject, JavaField jField) throws Exception{ + logr.log(JDILogger.LEVEL_VERYVERBOSE, " " + jField.getName() + "("+jField.getSignature()+")"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + byte signature = (byte)jField.getSignature().charAt(0); + if (jField.getSignature().equals("Ljava/lang/String;")){ //$NON-NLS-1$ + signature = (byte)'s'; + } + vctr.add(signature); + switch (signature){ + case '[': + try{ + if(jField.get(jObject) instanceof JavaObject){ + JavaObject jOut = (JavaObject)jField.get(jObject); + if (!objectMap.containsKey(jOut.getID().getAddress())){ + objectMap.put(jOut.getID().getAddress(), jOut); + } + logr.log(JDILogger.LEVEL_VERYVERBOSE, " ARRAY: " + jOut.getID().getAddress()); //$NON-NLS-1$ + addLongToVector(vctr, jOut.getID().getAddress()); + + }else if (jField.get(jObject) instanceof JavaClass){ + logr.logError(JDILogger.LEVEL_VERYVERBOSE, " ARRAY: Actually a class?!"); //$NON-NLS-1$ + addLongToVector(vctr, 0); + }else{ + logr.logError(JDILogger.LEVEL_VERYVERBOSE, " ARRAY: Not JavaObject"); //$NON-NLS-1$ + if (jField.get(jObject) == null){ + logr.logError(JDILogger.LEVEL_VERYVERBOSE, " ARRAY: is null"); //$NON-NLS-1$ + } + addLongToVector(vctr, 0); + } + } + catch(NullPointerException exxy){ + logr.logError(JDILogger.LEVEL_VERYVERBOSE, " ARRAY: Attemped access to field is null"); //$NON-NLS-1$ + exxy.printStackTrace(new PrintStream(logr.getErrorStream())); + addLongToVector(vctr, 0); + } + break; + case 's': + { + try{ + //Add the string to the lookup table + JavaObject jOut = (JavaObject)jField.get(jObject); + vctrs.put(jOut.getID().getAddress(), jField.getString(jObject)); + } + catch(NullPointerException exxy){} + catch(CorruptDataException exxy){ + //Take back what I said + int size = vctr.size(); + vctr.remove(size-1); + vctr.add((byte)'L'); + } + } + + case 'L': + case 't': + case 'g': + case 'l': + case 'c': + { + try{ + if(jField.get(jObject) instanceof JavaObject){ + JavaObject jOut = (JavaObject)jField.get(jObject); + addLongToVector(vctr, jOut.getID().getAddress()); + if (!objectMap.containsKey(jOut.getID().getAddress())){ + objectMap.put(jOut.getID().getAddress(), jOut); + } + logr.log(JDILogger.LEVEL_VERYVERBOSE, " " + jOut.getID().getAddress()); //$NON-NLS-1$ + }else{ + addLongToVector(vctr, 0); + logr.log(JDILogger.LEVEL_VERYVERBOSE, " Not JavaObject " + jField.get(jObject).getClass().getName()); //$NON-NLS-1$ + } + + + } + catch(NullPointerException exxy){ + logr.logError(JDILogger.LEVEL_VERYVERBOSE, " Attemped access to field is null"); //$NON-NLS-1$ + addIntToVector(vctr, 0); + } + } + break; + case 'F': + { + int bits = Float.floatToRawIntBits(jField.getFloat(jObject)); + addIntToVector(vctr, bits); + } + break; + case 'D': + { + long bits = Double.doubleToRawLongBits(jField.getDouble(jObject)); + addLongToVector(vctr, bits); + } + break; + case 'S': + vctr.add((byte)((jField.getShort(jObject) >> 8) & 0xFF)); + vctr.add((byte)(jField.getShort(jObject) & 0xFF)); + break; + case 'B': + vctr.add(jField.getByte(jObject)); + break; + case 'C': + vctr.add((byte)((jField.getChar(jObject) >> 8) & 0xFF)); + vctr.add((byte)(jField.getChar(jObject) & 0xFF)); + break; + case 'Z': + try{ + if (jField.getBoolean(jObject)){ + vctr.add((byte)1); + }else{ + vctr.add((byte)0); + } + }catch(IllegalArgumentException exxy){ + vctr.add((byte)0); + } + break; + case 'I': + addIntToVector(vctr, jField.getInt(jObject)); + break; + case 'J': + addLongToVector(vctr, jField.getLong(jObject)); + break; + default: + logr.log(JDILogger.LEVEL_VERYVERBOSE, " Unhandled type!"); //$NON-NLS-1$ + return false; + } + return true; + + } + + public Packet query(Packet pckt) throws Exception{ + if(image == null){ + try{ + startRead(); + + }catch (Exception exxy){ + throw exxy; + } + } + CommandPacket cpckt = (CommandPacket)pckt; + try{ + switch(cpckt.getCommandSet()){ + case COMMANDSET_VIRTUAL_MACHINE: + return virtualMachine(cpckt); + case COMMANDSET_REFERENCE_TYPE: + return referenceType(cpckt); + case COMMANDSET_CLASS_TYPE: + return classType(cpckt); + case COMMANDSET_METHOD: + return method(cpckt); + case COMMANDSET_OBJECT_REFERENCE: + return objectReference(cpckt); + case COMMANDSET_STRING_REFERENCE: + return stringReference(cpckt); + case COMMANDSET_THREAD_REFERENCE: + return threadReference(cpckt); + case COMMANDSET_ARRAY_REFERENCE: + return arrayReference(cpckt); + case COMMANDSET_EVENT_REQUEST: + return eventRequest(cpckt); + case COMMANDSET_STACK_FRAME: + return stackFrame(cpckt); + default: + logr.logError(JDILogger.LEVEL_VERBOSE, "Unknown command set"); //$NON-NLS-1$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED); + return rpckt; + } + } + catch(CorruptDataException exxy){ + logr.logError(JDILogger.LEVEL_VERBOSE, "Corrupt data."); //$NON-NLS-1$ + exxy.printStackTrace(new PrintStream(logr.getErrorStream())); + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INTERNAL); + rpckt.setData("CorruptDataException"); //$NON-NLS-1$ + return rpckt; + } + catch(Exception exxy){ + logr.logError(JDILogger.LEVEL_VERBOSE, "Exception occured: " + exxy.getMessage()); //$NON-NLS-1$ + exxy.printStackTrace(new PrintStream(logr.getErrorStream())); + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INTERNAL); + rpckt.setData("Exception"); //$NON-NLS-1$ + return rpckt; + } + } + + /** + * Load in the core file stored in pathToCore, into image. + * @throws Exception Upstream error + */ + + public void startRead() throws Exception{ + logr.log(JDILogger.LEVEL_VERBOSE, "Starting to read " + pathToCore); //$NON-NLS-1$ + + File f = new File(pathToCore); + try { + // FIXME Fill in appropriate means of finding an ImageFactory. + Class factoryClass = Class.forName("org.example.image.ImageFactory"); //$NON-NLS-1$ + ImageFactory factory = (ImageFactory) factoryClass.newInstance(); + image = factory.getImage(f); + } catch (ClassNotFoundException e) { + logr.logError(JDILogger.LEVEL_QUIET, "Could not find DTFJ factory class"); //$NON-NLS-1$ + e.printStackTrace(new PrintStream(logr.getErrorStream())); + errorCode = 1; + throw e; + } catch (IllegalAccessException e) { + logr.logError(JDILogger.LEVEL_QUIET, "IllegalAccessException for DTFJ factory class"); //$NON-NLS-1$ + e.printStackTrace(new PrintStream(logr.getErrorStream())); + errorCode = 2; + throw e; + } catch (InstantiationException e) { + logr.logError(JDILogger.LEVEL_QUIET, "Could not instantiate DTFJ factory class"); //$NON-NLS-1$ + e.printStackTrace(new PrintStream(logr.getErrorStream())); + errorCode = 3; + throw e; + } catch (IOException e) { + logr.logError(JDILogger.LEVEL_QUIET, "Could not find/use required file(s)"); //$NON-NLS-1$ + e.printStackTrace(new PrintStream(logr.getErrorStream())); + errorCode = 4; + throw e; + } + + if (image == null) { + return; + } + + logr.log(JDILogger.LEVEL_VERBOSE, "Extra Information"); //$NON-NLS-1$ + + try{ + logr.log(JDILogger.LEVEL_VERBOSE, " Creation Time:" + image.getCreationTime()); //$NON-NLS-1$ + }catch(Exception exxy){} + try{ + logr.log(JDILogger.LEVEL_VERBOSE, " Host Name: " + image.getHostName()); //$NON-NLS-1$ + }catch(Exception exxy){} + try{ + logr.log(JDILogger.LEVEL_VERBOSE, " Installed Memory: " + image.getInstalledMemory() + " bytes"); //$NON-NLS-1$ //$NON-NLS-2$ + }catch(Exception exxy){} + try{ + logr.log(JDILogger.LEVEL_VERBOSE, " Processor Count: " + image.getProcessorCount()); //$NON-NLS-1$ + }catch(Exception exxy){} + try{ + logr.log(JDILogger.LEVEL_VERBOSE, " Processor Type: " + image.getProcessorType()); //$NON-NLS-1$ + }catch(Exception exxy){} + try{ + logr.log(JDILogger.LEVEL_VERBOSE, "Processor Subtype: " + image.getProcessorSubType()); //$NON-NLS-1$ + }catch(Exception exxy){} + try{ + logr.log(JDILogger.LEVEL_VERBOSE, " System Type: " + image.getSystemType()); //$NON-NLS-1$ + }catch(Exception exxy){} + try{ + logr.log(JDILogger.LEVEL_VERBOSE, " System Subtype: " + image.getSystemSubType()); //$NON-NLS-1$ + }catch(Exception exxy){} + try{ + Iterator itr = image.getIPAddresses(); + while (itr.hasNext()){ + InetAddress addr = (InetAddress)itr.next(); + logr.log(JDILogger.LEVEL_VERBOSE, "IP: " + addr.toString()); //$NON-NLS-1$ + + } + }catch(Exception exxy){} + + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Building class list"); //$NON-NLS-1$ + this.classes = buildClasses(); + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Generating object list"); //$NON-NLS-1$ + this.objectMap = generateObjectHashmap(); + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Building field list"); //$NON-NLS-1$ + this.fieldList = buildFields(); + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Building method list"); //$NON-NLS-1$ + buildMethods(); + } + + /** + * Get the method object given a methodID + * @param methodID Address of the method as stored in the vector + * @return The DTFJ JavaMethod + */ + private JavaMethod getMethod(long methodID){ + if (intToMethod == null){ + buildMethods(); + } + return intToMethod.get(methodID); + + } + + /** + * Get the field object given a fieldID + * @param fieldID Address of a given field as stored in the vector + * @return The DTFJ JavaField + */ + private JavaField getField(long fieldID){ + if (fieldList == null){ + fieldList = buildFields(); + } + return fieldList.elementAt((int)fieldID); + + } + + /** + * Build the field vector by going through all the classes + * @return A vector containing a list of JDIJavaFields + */ + private Vector buildFields(){ + Vector fieldList = new Vector(); + Iterator jClasses = classes.values().iterator(); + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Building field list..."); //$NON-NLS-1$ + while(jClasses.hasNext()){ + JavaClass jClass = jClasses.next(); + Iterator jFields = jClass.getDeclaredFields(); + while(jFields.hasNext()){ + JavaField jField = (JavaField)jFields.next(); + try{ + fieldList.add(jField); + + }catch(Exception exxy){ + exxy.printStackTrace(new PrintStream(logr.getErrorStream())); + this.svr.stop(); + + } + + + } + } + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Built list of " + fieldList.size() + " fields"); //$NON-NLS-1$ //$NON-NLS-2$ + return fieldList; + + } + + /** + * Generate a list of fowards and backwards int to JavaMethod list. + */ + private void buildMethods(){ + intToMethod = new HashMap(); + methodToInt = new HashMap(); + Iterator jClasses = classes.values().iterator(); + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Building method list..."); //$NON-NLS-1$ + while(jClasses.hasNext()){ + JavaClass jClass = jClasses.next(); + Iterator jMethods = jClass.getDeclaredMethods(); + while(jMethods.hasNext()){ + JavaMethod jMethod = (JavaMethod)jMethods.next(); + try{ + int index = intToMethod.size(); + intToMethod.put(index, jMethod); + methodToInt.put(jMethod, index); + //logr.log(JDILogger.LEVEL_VERBOSE, jClass.getName()+"."+jMethod.getName()+"#"+methodList.indexOf(jMethod)); + }catch(Exception exxy){ + exxy.printStackTrace(new PrintStream(logr.getErrorStream())); + System.exit(1); + } + + + } + } + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Built list of " + intToMethod.size() + " methods"); //$NON-NLS-1$ //$NON-NLS-2$ + + } + + /** + * Given a JavaMethod and class id, return the id of the method + * @param refType The class id as found in the JavaClass vector + * @param jMethod The DTFJ JavaMethod object + * @return A unique ID for this method + */ + + private long getMethodId(long refType, JavaMethod jMethod){ + int id = methodToInt.get(jMethod); + if (id < 0 || id > methodToInt.size()){ + logr.logError(JDILogger.LEVEL_VERBOSE, " Could not find method in list"); //$NON-NLS-1$ + id = -1; + } + return id; + } + + /** + * Given a JavaField and class id, return the id of the field + * @param refType The class id as found in the JavaClass vector + * @param jField The DTFJ JavaField object + * @return A unique ID for this field + */ + + private long getFieldId(long refType, JavaField jField){ + int id = fieldList.indexOf(jField); + if (id < 0 || id > fieldList.size()){ + logr.logError(JDILogger.LEVEL_VERBOSE, " Could not find field in list"); //$NON-NLS-1$ + id = -1; + } + return id; + } + + + /** + * Given a vector, objectID, and fieldID, add the tagged value to the vector + * @param vctr The Byte vector for the current data segment + * @param objectID The unique objectID of the object we're inquiring about + * @param fieldID The unique fieldID of the field we're inquiring about + * @return false if we fail, true if we succeed + * @throws Exception Upstream exception thrown + */ + private boolean getFieldFromObject(Vector vctr, long objectID, long fieldID) throws Exception{ + + JavaField jField = getField(fieldID); + JavaObject jObject = getObject(objectID); + if (jField != null && jObject != null){ + return getValueFromField(vctr, jObject, jField); + } + logr.logError(JDILogger.LEVEL_VERBOSE, " Object " +objectID + " is not in the list of objects."); //$NON-NLS-1$ //$NON-NLS-2$ + + + logr.logError(JDILogger.LEVEL_VERBOSE, " Cannot find class field from object"); //$NON-NLS-1$ + return false; + } + + /** + * Given a vector, reffTypeID, and fieldID, add the tagged value to the vector + * @param vctr The Byte vector for the current data segment + * @param refType The unique class ID of the object we're inquiring about + * @param fieldID The unique fieldID of the field we're inquiring about + * @return false if we fail, true if we succeed + * @throws Exception Upstream exception thrown + */ + private boolean getFieldFromClass(Vector vctr, long refType, long fieldID) throws Exception{ + + JavaClass javaClass = getClass(refType); + if (javaClass != null){ + JavaField jField = getField(fieldID); + if (jField != null){ + return getValueFromField(vctr, javaClass.getObject(), jField); + } + logr.logError(JDILogger.LEVEL_VERYVERBOSE, " No such field"); //$NON-NLS-1$ + + }else{ + logr.logError(JDILogger.LEVEL_VERYVERBOSE, " No such class"); //$NON-NLS-1$ + return false; + } + + return false; + } + + /** + * Build a hashmap using the JavaClass address as a unique ID and key + * @return A hashmap containing all the classes and addresses + */ + private HashMap buildClasses() { + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Building class list"); //$NON-NLS-1$ + HashMap classes = new HashMap(); + Iterator asIt = image.getAddressSpaces( ); + while ( asIt.hasNext( ) ) + { + ImageAddressSpace as = (ImageAddressSpace) asIt.next( ); + Iterator prIt = as.getProcesses( ); + while ( prIt.hasNext( ) ){ + ImageProcess process = (ImageProcess) prIt.next( ); + + Iterator runTimesIt = process.getRuntimes( ); + while ( runTimesIt.hasNext( ) ) + { + JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( ); + Iterator classLoaders = javaRT.getJavaClassLoaders(); + while (classLoaders.hasNext()){ + + JavaClassLoader javaCL = (JavaClassLoader)classLoaders.next(); + Iterator javaClasses = javaCL.getDefinedClasses(); + + while (javaClasses.hasNext()){ + JavaClass javaClass = (JavaClass)javaClasses.next(); + + classes.put(javaClass.getID().getAddress(), javaClass); + + + } + } + } + } + } + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Built list of " + classes.size() + " classes"); //$NON-NLS-1$ //$NON-NLS-2$ + return classes; + } + + /** + * Convert a Vector to a byte array + * @param vctr The Vector to convert + * @return An array consisting of bytes (Not Bytes) + */ + + + public static byte[] vectorToByte(Vector vctr){ + Byte []barray = new Byte[vctr.size()]; + vctr.copyInto(barray); + //TODO - A better way to do this? + byte []barray2 = new byte[barray.length]; + for (int i = 0; i < barray.length; i++){ + barray2[i] = barray[i]; + } + return barray2; + } + + + /** + * getByteFromInt is used to break down an int into a byte + * @param orig The original integer + * @param index Which byte to get (0-3 inclusive) + * @return The byte + */ + public static byte getByteFromInt(int orig, int index){ + if (index < 0 || index > 3) + throw new ArrayIndexOutOfBoundsException(); + //Mask out the 4 bytes + int mask = 0xFF; + + //Align the mask to what we want + mask = mask << (index*8); + + //Mask out the byte we want + orig = orig & mask; + + //Align back our new value + orig = orig >> (index*8); + + //Truncate the rest of the useless bytes + return (byte)orig; + + } + + /** + * Add a 64bit long to the end of the Byte Vector + * @param vctr Vector to add the bytes to + * @param inLong The long to add + */ + + public static void addLongToVector(Vector vctr, long inLong){ + int topInt = (int)(inLong >> 32) & 0xFFFFFFFF; + int bottomInt = (int)inLong & 0xFFFFFFFF; + + vctr.add(getByteFromInt(topInt, 3)); + vctr.add(getByteFromInt(topInt, 2)); + vctr.add(getByteFromInt(topInt, 1)); + vctr.add(getByteFromInt(topInt, 0)); + + vctr.add(getByteFromInt(bottomInt, 3)); + vctr.add(getByteFromInt(bottomInt, 2)); + vctr.add(getByteFromInt(bottomInt, 1)); + vctr.add(getByteFromInt(bottomInt, 0)); + } + + /** + * Add a 32bit int to the front of the Byte Vector + * @param vctr Vector to add the bytes to + * @param inInt The int to add + */ + public static void addIntToVectorFront(Vector vctr, int inInt){ + vctr.add(0, getByteFromInt(inInt, 3)); + vctr.add(1, getByteFromInt(inInt, 2)); + vctr.add(2, getByteFromInt(inInt, 1)); + vctr.add(3, getByteFromInt(inInt, 0)); + } + + /** + * Add a 32bit int to the end of the Byte Vector + * @param vctr Vector to add the bytes to + * @param inInt The int to add + */ + public static void addIntToVector(Vector vctr, int inInt){ + vctr.add(getByteFromInt(inInt, 3)); + vctr.add(getByteFromInt(inInt, 2)); + vctr.add(getByteFromInt(inInt, 1)); + vctr.add(getByteFromInt(inInt, 0)); + } + + /** + * Add a string to the end of the Byte Vector as specified in the JDWP docs (4 byte length + ASCII chars) + * @param vctr Vector to add the bytes to + * @param inString The string to add + */ + public static void addStringToVector(Vector vctr, String inString){ + addIntToVector(vctr, inString.length()); + + byte[] str = inString.getBytes(); + for (int i = 0; i < str.length; i++){ + vctr.add(str[i]); + } + } + + /** + * Given a byte array, extract a string as defined in the JDWP specs + * @param inData The byte array to pull the data from + * @param offset The index of the string (which is the length of the string) + * @return The resultant string + */ + public static String getStringFromBytes(byte []inData, int offset){ + int length = createIntFromBytes(inData, offset, 4); + String ret = ""; //$NON-NLS-1$ + for(int i = offset + 4; i < offset + 4 + length; i++){ + ret = ret + (char)inData[i]; + } + + + return ret; + } + + /** + * Given a byte array, extract a 32bit int + * @param inData The byte array to pull the data from + * @param offset The index of the int + * @param size How many bytes to extract + * @return The 32bit int + */ + public static int createIntFromBytes(byte []inData, int offset, int size){ + + + int ret = 0; + if (size == 0) + size = 4; + if (size != 4){ + throw new NumberFormatException("createIntFromBytes should be 4 bytes"); //$NON-NLS-1$ + } + for(int i = offset; i < offset + size; i++){ + ret = ret << 8; + ret |= (inData[i] & 0xFF); + } + + return ret; + + } + + /** + * Given a byte array, extract a 64bit long + * @param inData The byte array to pull the data from + * @param offset The index of the int + * @param size How many bytes to extract + * @return The 64bit long + */ + public static long createLongFromBytes(byte []inData, int offset, int size){ + long ret = 0; + if (size == 0) + size = 8; + if (size != 8){ + throw new NumberFormatException("createLongFromBytes should be 8 bytes"); //$NON-NLS-1$ + } + for(int i = offset; i < offset + size; i++){ + ret = ret << 8; + ret |= (inData[i] & 0xFF); + } + + return ret; + + } + + /** + * Return whether a class is an interface or not + * @param classID The id of the class + * @return true if the class is an interface + * @throws CorruptDataException + */ + private boolean isInterface(long classID) throws CorruptDataException{ + //Use modifier + if (classes == null){ + buildClasses(); + } + JavaClass jClass = getClass(classID); + if (jClass != null){ + if (Modifier.isInterface(jClass.getModifiers())){ + return true; + } + } + return false; + } + + /** + * Given a classID, get the DTFJ JavaClass + * @param classID The unique class ID + * @return The DTFJ JavaClass + * @throws CorruptDataException + */ + private JavaClass getClass(long classID){ + if (classes == null){ + classes = buildClasses(); + } + return classes.get(classID); + + } + + /** + * Given a classID, check to see if the ID is actually a class or an object + * @param classID The classID + * @return true if classID is a class, false if it is not + * @throws CorruptDataException + */ + private boolean isClass(long classID){ + if (classes == null){ + classes = buildClasses(); + } + return classes.containsKey(classID); + } + + /** + * Given a classID and a methodID, get the lowest line number known in all stack frames + * @param refType The class ID of the method + * @param methodID The method ID + * @return The lowest known line number + * @throws Exception + */ + private int findLowestLineRef(long refType, long methodID) throws Exception{ + int lowest = 1999999999; + Iterator asIt = image.getAddressSpaces( ); + while ( asIt.hasNext( ) ) + { + ImageAddressSpace as = (ImageAddressSpace) asIt.next( ); + Iterator prIt = as.getProcesses( ); + + while ( prIt.hasNext( ) ) + { + ImageProcess process = (ImageProcess) prIt.next( ); + Iterator runTimesIt = process.getRuntimes( ); + while ( runTimesIt.hasNext( ) ) + { + JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( ); + Iterator thds = javaRT.getThreads(); + while(thds.hasNext()){ + Object tmpobj = thds.next(); + if (tmpobj instanceof CorruptData){ + //ignore this thread + }else{ + JavaThread thd = (JavaThread) tmpobj; + Iterator frames = thd.getStackFrames(); + while(frames.hasNext()){ + JavaStackFrame jStackFrame = (JavaStackFrame)frames.next(); + JavaLocation jLocation = jStackFrame.getLocation(); + JavaMethod jMethod = jLocation.getMethod(); + JavaClass jClass = jMethod.getDeclaringClass(); + + + if (getMethodId(refType, jMethod) == methodID && jClass.getID().getAddress() == refType){ + int line = -1; + try{ + line = jLocation.getLineNumber(); + } + catch(Exception exxy){} + if (line > 0){ + if (lowest > line){ + lowest = line; + } + } + } + } + } + } + } + } + } + return lowest; + } + + /** + * Given a classID and a methodID, get the highest line number known in all stack frames + * @param refType The class ID of the method + * @param methodID The method ID + * @return The highest known line number + * @throws Exception + */ + private int findHighestLineRef(long refType, long methodID) throws Exception{ + int highest = 0; + Iterator asIt = image.getAddressSpaces( ); + while ( asIt.hasNext( ) ) + { + ImageAddressSpace as = (ImageAddressSpace) asIt.next( ); + Iterator prIt = as.getProcesses( ); + + while ( prIt.hasNext( ) ) + { + ImageProcess process = (ImageProcess) prIt.next( ); + Iterator runTimesIt = process.getRuntimes( ); + while ( runTimesIt.hasNext( ) ) + { + JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( ); + Iterator thds = javaRT.getThreads(); + while(thds.hasNext()){ + Object tmpobj = thds.next(); + if (tmpobj instanceof CorruptData){ + //ignore this thread + }else{ + JavaThread thd = (JavaThread) tmpobj; + Iterator frames = thd.getStackFrames(); + while(frames.hasNext()){ + JavaStackFrame jStackFrame = (JavaStackFrame)frames.next(); + JavaLocation jLocation = jStackFrame.getLocation(); + JavaMethod jMethod = jLocation.getMethod(); + JavaClass jClass = jMethod.getDeclaringClass(); + + + if (getMethodId(refType, jMethod) == methodID && jClass.getID().getAddress() == refType){ + int line = -1; + try{ + line = jLocation.getLineNumber(); + } + catch(Exception exxy){} + if (line > 0){ + if (line > highest){ + highest = line; + } + } + } + } + } + } + } + } + } + return highest; + } + + /** + * Take care of the virtualMachine command set of the JDWP specs. + * @param cpckt The incoming command packet request + * @return The reply packet to be returned to the client + * @throws Exception + */ + public ReplyPacket virtualMachine(CommandPacket cpckt) throws Exception{ + if (cpckt.getCommand() == VIRTUAL_MACHINE_VERSION){ + logr.log(JDILogger.LEVEL_VERBOSE, "Version()"); //$NON-NLS-1$ + Iterator asIt = image.getAddressSpaces( ); + while ( asIt.hasNext( ) ) + { + ImageAddressSpace as = (ImageAddressSpace) asIt.next( ); + Iterator prIt = as.getProcesses( ); + while ( prIt.hasNext( ) ){ + ImageProcess process = (ImageProcess) prIt.next( ); + + Iterator runTimesIt = process.getRuntimes( ); + while ( runTimesIt.hasNext( ) ) + { + JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( ); + //Since there doesn't seem to be a matching DTFJ call to get + //the information for JDWP, lets call NOT_IMPLEMENTED, but really + //attach some information back + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + String description = "JDI Post Mortem Debugger"; //$NON-NLS-1$ + String vmVersion = javaRT.getVersion(); + String vmName = "JDI PMD"; //$NON-NLS-1$ + + int jdwpMajor = 1; + int jdwpMinor = 4; + + //We now have all the information for the reply. Put it all together + Vector vctr = new Vector(); + addStringToVector(vctr, description); + addIntToVector(vctr, jdwpMajor); + addIntToVector(vctr, jdwpMinor); + addStringToVector(vctr, vmVersion); + addStringToVector(vctr, vmName); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + + } + } + } + + }else if (cpckt.getCommand() == VIRTUAL_MACHINE_CLASSES_BY_SIGNATURE){ + Vector vctr = new Vector(); + byte []inData = cpckt.getByteData(); + String signature = getStringFromBytes(inData, 0); + logr.log(JDILogger.LEVEL_VERBOSE, "ClassesBySignature(" + signature + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + int count = 0; + Iterator javaClasses = classes.values().iterator(); + while (javaClasses.hasNext()){ + JavaClass javaClass = javaClasses.next(); + String searched = javaClass.getName(); + + if (searched.equals(signature)){ + count++; + vctr.add((byte)1); + addLongToVector(vctr, javaClass.getID().getAddress()); + //Verified Prepared and Initialized + addIntToVector(vctr, 1 | 2 | 4); + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Match: " + javaClass.getName()); //$NON-NLS-1$ + }else{ + String mangledName = "L" + searched + ";"; //$NON-NLS-1$ //$NON-NLS-2$ + if (mangledName.equals(signature)){ + count++; + vctr.add((byte)1); + addLongToVector(vctr, javaClass.getID().getAddress()); + //Verified Prepared and Initialized + addIntToVector(vctr, 1 | 2 | 4); + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Mangled Match: " + javaClass.getName()); //$NON-NLS-1$ + }else{ + String secondMangle = "[" + searched + ";"; //$NON-NLS-1$ //$NON-NLS-2$ + if (secondMangle.equals(signature)){ + count++; + vctr.add((byte)1); + addLongToVector(vctr, javaClass.getID().getAddress()); + //Verified Prepared and Initialized + addIntToVector(vctr, 1 | 2 | 4); + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Really mangled match: " + javaClass.getName()); //$NON-NLS-1$ + } + } + } + + } + //Add the count to the front of the vector + addIntToVectorFront(vctr, count); + + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + }else if (cpckt.getCommand() == VIRTUAL_MACHINE_ALL_CLASSES){ + logr.log(JDILogger.LEVEL_VERBOSE, "AllClasses()"); //$NON-NLS-1$ + Vector vctr = new Vector(); + int count = 0; + Iterator classList = classes.values().iterator(); + while(classList.hasNext()){ + JavaClass javaClass = (JavaClass)classList.next(); + long typeID = javaClass.getID().getAddress(); + String signature; + + if (javaClass.isArray()){ + vctr.add((byte)3); + signature = "L" + javaClass.getName() + ";"; //$NON-NLS-1$ //$NON-NLS-2$ + }else if (isInterface(typeID)){ + vctr.add((byte)2); + signature = "L" + javaClass.getName() + ";"; //$NON-NLS-1$ //$NON-NLS-2$ + }else{ + vctr.add((byte)1); + signature = "L" + javaClass.getName() + ";"; //$NON-NLS-1$ //$NON-NLS-2$ + } + + int status = 7; + addLongToVector(vctr, typeID); + addStringToVector(vctr, signature); + addIntToVector(vctr, status); + count++; + + + } + + logr.log(JDILogger.LEVEL_VERYVERBOSE, " " + count +" class(es) found"); //$NON-NLS-1$ //$NON-NLS-2$ + addIntToVectorFront(vctr, count); + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + }else if (cpckt.getCommand() == VIRTUAL_MACHINE_ALL_THREADS){ + logr.log(JDILogger.LEVEL_VERBOSE, "AllThreads()"); //$NON-NLS-1$ + Iterator asIt = image.getAddressSpaces( ); + while ( asIt.hasNext( ) ) + { + ImageAddressSpace as = (ImageAddressSpace) asIt.next( ); + Iterator prIt = as.getProcesses( ); + + while ( prIt.hasNext( ) ) + { + ImageProcess process = (ImageProcess) prIt.next( ); + Iterator runTimesIt = process.getRuntimes( ); + while ( runTimesIt.hasNext( ) ) + { + JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( ); + Iterator thds = javaRT.getThreads(); + Vector vctr = new Vector(); + int count = 0; + while(thds.hasNext()){ + Object tmpobj = thds.next(); + if (tmpobj instanceof CorruptData){ + //ignore this thread + }else{ + count++; + JavaThread thd = (JavaThread)tmpobj; + long hash = thd.getObject().getID().getAddress(); + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread hash " + thd.getName() + " is " + hash); //$NON-NLS-1$ //$NON-NLS-2$ + addLongToVector(vctr, hash); + } + + } + addIntToVectorFront(vctr, count); + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + byte []barray2 = vectorToByte(vctr); + rpckt.setData(barray2); + return rpckt; + + + } + + } + } + }else if (cpckt.getCommand() == VIRTUAL_MACHINE_DISPOSE){ + //This is a disconnect request + logr.log(JDILogger.LEVEL_VERBOSE, "Dispose()"); //$NON-NLS-1$ + svr.disconnect(cpckt.getVSock()); + return null; + }else if (cpckt.getCommand() == VIRTUAL_MACHINE_IDSIZES){ + //Here we specify a 4 byte (32bit) id size for everything + //1.7 says that there are 5 fields, each with the number of bytes + //used to identify each id. + logr.log(JDILogger.LEVEL_VERBOSE, "IDSizes()"); //$NON-NLS-1$ + Vector vctr = new Vector(); + //fieldID + addIntToVector(vctr, 8); + //methodID + addIntToVector(vctr, 8); + //objectID + addIntToVector(vctr, 8); + //referenceTypeID (refType) + addIntToVector(vctr, 8); + //frameID + addIntToVector(vctr, 8); + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + }else if (cpckt.getCommand() == VIRTUAL_MACHINE_SUSPEND){ + //Suspend the whole VM. Which is what we're already doing + //Just play along with it. + logr.log(JDILogger.LEVEL_VERBOSE, "Suspend()"); //$NON-NLS-1$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + return rpckt; + }else if (cpckt.getCommand() == VIRTUAL_MACHINE_RESUME){ + //Resume the VM. Which we can't do. + //Just pretend. + logr.log(JDILogger.LEVEL_VERBOSE, "Resume()"); //$NON-NLS-1$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + return rpckt; + }else if (cpckt.getCommand() == VIRTUAL_MACHINE_EXIT){ + shutDownDTFJ(); + //This is a disconnect request + logr.log(JDILogger.LEVEL_VERBOSE, "Exit()"); //$NON-NLS-1$ + logr.log(JDILogger.LEVEL_NORMAL, "Remove client asked termination of server"); //$NON-NLS-1$ + svr.stop(); + svr = null; + return null; + }else if (cpckt.getCommand() == VIRTUAL_MACHINE_CAPABILITIES_NEW){ + logr.log(JDILogger.LEVEL_VERBOSE, "CapabilitiesNew()"); //$NON-NLS-1$ + //This is the capabilities request. + byte canWatchFieldModification = 0; + byte canWatchFieldAccess = 0; + byte canGetBytecodes = 1; + byte canGetSyntheticAttribute = 0; + byte canGetOwnedMonitorInfo = 0; + byte canGetCurrentContendedMonitor = 0; + byte canGetMonitorInfo = 0; + byte canRedefineClasses = 0; + byte canAddMethod = 0; + byte canUnrestrictedlyRedfineClasses = 0; + byte canPopFrames = 0; + byte canUseInstanceFilters = 0; + byte canGetSourceDebugExtension = 1; + byte canRequestVMDeathEvent = 0; + byte canSetDefaultStratum = 0; + + Vector vctr = new Vector(); + vctr.add(canWatchFieldModification); + vctr.add(canWatchFieldAccess); + vctr.add(canGetBytecodes); + vctr.add(canGetSyntheticAttribute); + vctr.add(canGetOwnedMonitorInfo); + vctr.add(canGetCurrentContendedMonitor); + vctr.add(canGetMonitorInfo); + vctr.add(canRedefineClasses); + vctr.add(canAddMethod); + vctr.add(canUnrestrictedlyRedfineClasses); + vctr.add(canPopFrames); + vctr.add(canUseInstanceFilters); + vctr.add(canGetSourceDebugExtension); + vctr.add(canRequestVMDeathEvent); + vctr.add(canSetDefaultStratum); + //Fill unused + for (int i = 0; i < 17; i++){ + vctr.add((byte)0); + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED); + return rpckt; + + + } + /** + * Take care of the referenceType command set of the JDWP specs. + * @param cpckt The incoming command packet request + * @return The reply packet to be returned to the client + * @throws Exception + */ + public ReplyPacket referenceType(CommandPacket cpckt) throws Exception{ + if (cpckt.getCommand() == REFERENCE_TYPE_SIGNATURE){ + Vector vctr = new Vector(); + byte []inData = cpckt.getByteData(); + long refType = createLongFromBytes(inData, 0, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "Signature(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + + JavaClass javaClass = getClass(refType); + if (javaClass != null){ + logr.log(JDILogger.LEVEL_VERYVERBOSE, " L" + javaClass.getName() + ";"); //$NON-NLS-1$ //$NON-NLS-2$ + addStringToVector(vctr, "L" + javaClass.getName() + ";"); //$NON-NLS-1$ //$NON-NLS-2$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + } + + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT); + return rpckt; + }else if (cpckt.getCommand() == REFERENCE_TYPE_CLASS_LOADER){ + byte []inData = cpckt.getByteData(); + long refType = createLongFromBytes(inData, 0, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "ClassLoader(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + + JavaClass javaClass = getClass(refType); + if (javaClass != null){ + Vector vctr = new Vector(); + addLongToVector(vctr, javaClass.getClassLoader().getObject().getID().getAddress()); + logr.log(JDILogger.LEVEL_VERYVERBOSE, " " + javaClass.getClassLoader().getObject().getID().getAddress()); //$NON-NLS-1$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + + } + + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT); + return rpckt; + }else if (cpckt.getCommand() == REFERENCE_TYPE_MODIFIERS){ + byte []inData = cpckt.getByteData(); + long refType = createLongFromBytes(inData, 0, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "Modifiers(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + + JavaClass javaClass = getClass(refType); + if (javaClass != null){ + Vector vctr = new Vector(); + addIntToVectorFront(vctr,javaClass.getModifiers()); + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + } + + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT); + return rpckt; + }else if (cpckt.getCommand() == REFERENCE_TYPE_FIELDS){ + byte []inData = cpckt.getByteData(); + long refType = createLongFromBytes(inData, 0, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "Fields(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + + JavaClass javaClass = getClass(refType); + if (javaClass != null){ + Iterator javaFields = javaClass.getDeclaredFields(); + logr.log(JDILogger.LEVEL_VERYVERBOSE, javaClass.getName() + ":"); //$NON-NLS-1$ + Vector vctr = new Vector(); + int count = 0; + while (javaFields.hasNext()){ + JavaField jField = (JavaField)javaFields.next(); + + long fieldID = getFieldId(refType, jField); + String name = jField.getName(); + String signature = jField.getSignature(); + int modBits = jField.getModifiers(); + addLongToVector(vctr, fieldID); + addStringToVector(vctr, name); + addStringToVector(vctr, signature); + addIntToVector(vctr, modBits); + logr.log(JDILogger.LEVEL_VERYVERBOSE, " " + name + " (" + signature + "," + fieldID + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + count++; + } + addIntToVectorFront(vctr,count); + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Found " + count + " fields(s)"); //$NON-NLS-1$ //$NON-NLS-2$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + } + + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT); + return rpckt; + }else if (cpckt.getCommand() == REFERENCE_TYPE_METHODS){ + byte []inData = cpckt.getByteData(); + long refType = createLongFromBytes(inData, 0, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "Methods(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + + JavaClass javaClass = getClass(refType); + if (javaClass != null){ + Iterator javaMethods = javaClass.getDeclaredMethods(); + logr.log(JDILogger.LEVEL_VERYVERBOSE, javaClass.getName() + ":"); //$NON-NLS-1$ + Vector vctr = new Vector(); + int count = 0; + while (javaMethods.hasNext()){ + JavaMethod jMethod = (JavaMethod)javaMethods.next(); + long methodID = getMethodId(refType, jMethod); + String name = jMethod.getName(); + String signature = jMethod.getSignature(); + int modBits = jMethod.getModifiers(); + addLongToVector(vctr, methodID); + addStringToVector(vctr, name); + addStringToVector(vctr, signature); + addIntToVector(vctr, modBits); + logr.log(JDILogger.LEVEL_VERYVERBOSE, " " + name + " (" + signature + ", " + methodID + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + count++; + } + addIntToVectorFront(vctr,count); + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Found " + count + " method(s)"); //$NON-NLS-1$ //$NON-NLS-2$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + } + + + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT); + return rpckt; + }else if (cpckt.getCommand() == REFERENCE_TYPE_GET_VALUES){ + byte [] inData = cpckt.getByteData(); + long refType = createLongFromBytes(inData, 0, 8); + int fields = createIntFromBytes(inData, 8, 4); + logr.log(JDILogger.LEVEL_VERBOSE, "ReferenceType.GetValues(" + refType + ", " + fields + ",...)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + Vector vctr = new Vector(); + + addIntToVector(vctr, fields); + + for(int i = 0; i < fields; i++){ + long fieldID = createLongFromBytes(inData, 12 + (i * 8), 8); + logr.log(JDILogger.LEVEL_VERYVERBOSE, " " + i + " of " + fields + " {" + fieldID+"}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + if (!getFieldFromClass(vctr, refType, fieldID)){ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT); + return rpckt; + } + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + }else if (cpckt.getCommand() == REFERENCE_TYPE_SOURCE_FILE){ + byte [] inData = cpckt.getByteData(); + long refType = createLongFromBytes(inData, 0, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "SourceFile(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + Iterator asIt = image.getAddressSpaces( ); + while ( asIt.hasNext( ) ) + { + ImageAddressSpace as = (ImageAddressSpace) asIt.next( ); + Iterator prIt = as.getProcesses( ); + + while ( prIt.hasNext( ) ) + { + ImageProcess process = (ImageProcess) prIt.next( ); + Iterator runTimesIt = process.getRuntimes( ); + while ( runTimesIt.hasNext( ) ) + { + JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( ); + Iterator thds = javaRT.getThreads(); + while(thds.hasNext()){ + Object tmpobj = thds.next(); + if (tmpobj instanceof CorruptData){ + //ignore this thread + }else{ + JavaThread thd = (JavaThread) tmpobj; + Iterator frames = thd.getStackFrames(); + while(frames.hasNext()){ + JavaStackFrame jStackFrame = (JavaStackFrame)frames.next(); + JavaLocation jLocation = jStackFrame.getLocation(); + JavaMethod jMethod = jLocation.getMethod(); + JavaClass jClass = jMethod.getDeclaringClass(); + + + if (jClass.getID().getAddress() == refType){ + Vector vctr = new Vector(); + try{ + addStringToVector(vctr, jLocation.getFilename()); + logr.log(JDILogger.LEVEL_VERBOSE, " " + jLocation.getFilename()); //$NON-NLS-1$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + } + catch(Exception exxy){ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_ABSENT_INFORMATION); + return rpckt; + } + } + } + } + } + } + } + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_ABSENT_INFORMATION); + return rpckt; + + }else if (cpckt.getCommand() == REFERENCE_TYPE_INTERFACES){ + byte []inData = cpckt.getByteData(); + long refType = createLongFromBytes(inData, 0, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "Interfaces(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + + JavaClass javaClass = getClass(refType); + if (javaClass != null){ + Iterator javaInterfaces = javaClass.getInterfaces(); + logr.log(JDILogger.LEVEL_VERYVERBOSE, javaClass.getName() + ":"); //$NON-NLS-1$ + Vector vctr = new Vector(); + int count = 0; + while (javaInterfaces.hasNext()){ + String iFaceName = (String)javaInterfaces.next(); + JavaClass jClass = javaClass.getClassLoader().findClass(iFaceName); + long interfaceID; + if (jClass == null){ + interfaceID = 0; + }else{ + interfaceID = jClass.getID().getAddress(); + } + addLongToVector(vctr, interfaceID); + logr.log(JDILogger.LEVEL_VERYVERBOSE, " " + interfaceID); //$NON-NLS-1$ + + count++; + } + addIntToVectorFront(vctr,count); + logr.log(JDILogger.LEVEL_VERYVERBOSE, " Found " + count + " interface(s)"); //$NON-NLS-1$ //$NON-NLS-2$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + } + + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT); + return rpckt; + }else if (cpckt.getCommand() == REFERENCE_TYPE_SOURCE_DEBUG_EXTENSION){ + byte []inData = cpckt.getByteData(); + long refType = createLongFromBytes(inData, 0, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "SourceDebugExtension(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + Vector vctr = new Vector(); + addStringToVector(vctr, ""); //$NON-NLS-1$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED); + return rpckt; + } + + /** + * Take care of the classType command set of the JDWP specs. + * @param cpckt The incoming command packet request + * @return The reply packet to be returned to the client + * @throws Exception + */ + private ReplyPacket classType(CommandPacket cpckt) throws Exception{ + if (cpckt.getCommand() == 1){ + Vector vctr = new Vector(); + byte []inData = cpckt.getByteData(); + long refType = createLongFromBytes(inData, 0, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "Superclass(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + + JavaClass javaClass = getClass(refType); + if (javaClass != null){ + try{ + JavaClass jSuperClass = javaClass.getSuperclass(); + addLongToVector(vctr, jSuperClass.getID().getAddress()); + logr.log(JDILogger.LEVEL_VERYVERBOSE, " " + jSuperClass.getID().getAddress()); //$NON-NLS-1$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + }catch(NullPointerException exxy){ + addLongToVector(vctr, 0); + logr.log(JDILogger.LEVEL_VERYVERBOSE, " Class "+javaClass.getName()+"{"+javaClass.getID().getAddress()+"} has no superclass"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + + + } + } + + } + + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED); + return rpckt; + + } + + /** + * Take care of the method command set of the JDWP specs. + * @param cpckt The incoming command packet request + * @return The reply packet to be returned to the client + * @throws Exception + */ + private ReplyPacket method(CommandPacket cpckt) throws Exception{ + if (cpckt.getCommand() == 1){ + byte [] inData = cpckt.getByteData(); + long refType = createLongFromBytes(inData, 0, 8); + long methodID = createLongFromBytes(inData, 8, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "LineTable(" + refType + "," + methodID + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + Iterator asIt = image.getAddressSpaces( ); + while ( asIt.hasNext( ) ) + { + ImageAddressSpace as = (ImageAddressSpace) asIt.next( ); + Iterator prIt = as.getProcesses( ); + + while ( prIt.hasNext( ) ) + { + ImageProcess process = (ImageProcess) prIt.next( ); + Iterator runTimesIt = process.getRuntimes( ); + while ( runTimesIt.hasNext( ) ) + { + JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( ); + Iterator thds = javaRT.getThreads(); + while(thds.hasNext()){ + Object tmpobj = thds.next(); + if (tmpobj instanceof CorruptData){ + //ignore this thread + }else{ + JavaThread thd = (JavaThread) tmpobj; + Iterator frames = thd.getStackFrames(); + while(frames.hasNext()){ + JavaStackFrame jStackFrame = (JavaStackFrame)frames.next(); + JavaLocation jLocation = jStackFrame.getLocation(); + JavaMethod jMethod = jLocation.getMethod(); + JavaClass jClass = jMethod.getDeclaringClass(); + + + if (getMethodId(refType, jMethod) == methodID && jClass.getID().getAddress() == refType){ + int line = -1; + try{ + line = jLocation.getLineNumber(); + } + catch(CorruptDataException exxy){ + logr.log(JDILogger.LEVEL_VERYVERBOSE, " CorruptData for:"); //$NON-NLS-1$ + } + catch(DataUnavailable exxy){ + logr.log(JDILogger.LEVEL_VERYVERBOSE, " DataUnavailable for:"); //$NON-NLS-1$ + } + + + Vector vctr = new Vector(); + if (line > 0){ + + int lowest = findLowestLineRef(refType, methodID) - 1; + int highest = findHighestLineRef(refType, methodID) + 1; + logr.log(JDILogger.LEVEL_VERYVERBOSE, " (L)" + jClass.getName() + "." + jMethod.getName() + ":" + lowest + "<" + line + ">" + highest); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ + //Code index start + addLongToVector(vctr, lowest); + //Code index end + addLongToVector(vctr, highest); + //Number of lines + addIntToVector(vctr, highest - lowest); + for(int i = lowest; i <= highest; i++){ + addLongToVector(vctr, i); + addIntToVector(vctr, i); + } + }else{ + logr.log(JDILogger.LEVEL_VERYVERBOSE, " (N)" + jClass.getName() + "." + jMethod.getName() + ":" + line); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + //Code index start + addLongToVector(vctr, 41); + //Code index end + addLongToVector(vctr, 43); + //Number of lines + //We're native right now. + addIntToVector(vctr, 0); + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + } + + } + } + } + } + } + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INTERNAL); + return rpckt; + }else if (cpckt.getCommand() == 2){ + byte [] inData = cpckt.getByteData(); + long refType = createLongFromBytes(inData, 0, 8); + long methodID = createLongFromBytes(inData, 8, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "Method.VariableTable(" + refType + "," + methodID + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + int slotsUsed = 0; + Iterator asIt = image.getAddressSpaces( ); + while ( asIt.hasNext( ) ) + { + ImageAddressSpace as = (ImageAddressSpace) asIt.next( ); + Iterator prIt = as.getProcesses( ); + + while ( prIt.hasNext( ) ) + { + ImageProcess process = (ImageProcess) prIt.next( ); + Iterator runTimesIt = process.getRuntimes( ); + while ( runTimesIt.hasNext( ) ) + { + JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( ); + Iterator thds = javaRT.getThreads(); + while(thds.hasNext()){ + Object tmpobj = thds.next(); + if (tmpobj instanceof CorruptData){ + //ignore this thread + }else{ + JavaThread thd = (JavaThread) tmpobj; + Iterator frames = thd.getStackFrames(); + while(frames.hasNext()){ + JavaStackFrame jStackFrame = (JavaStackFrame)frames.next(); + JavaLocation jLocation = jStackFrame.getLocation(); + JavaMethod jMethod = jLocation.getMethod(); + JavaClass jClass = jMethod.getDeclaringClass(); + + if (getMethodId(refType, jMethod) == methodID && jClass.getID().getAddress() == refType){ + if (!Modifier.isStatic(jMethod.getModifiers())){ + int line = -1; + try{ + line = jLocation.getLineNumber(); + } + catch(Exception exxy){} + Vector vctr = new Vector(); + if (line > 0){ + addIntToVector(vctr, 1); + addIntToVector(vctr, 1); + + addLongToVector(vctr, 0); + addStringToVector(vctr, "this"); //$NON-NLS-1$ + + addStringToVector(vctr, "L" + jClass.getName() + ";"); //$NON-NLS-1$ //$NON-NLS-2$ + int highest = findHighestLineRef(refType, methodID); + addIntToVector(vctr, highest + 5); + addIntToVector(vctr, slotsUsed++); + logr.log(JDILogger.LEVEL_VERYVERBOSE, " L" + jClass.getName() + ";"); //$NON-NLS-1$ //$NON-NLS-2$ + }else{ + addIntToVector(vctr, 0); + addIntToVector(vctr, 0); + logr.log(JDILogger.LEVEL_VERYVERBOSE, " Line information not available"); //$NON-NLS-1$ + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + + return rpckt; + + + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_ABSENT_INFORMATION); + return rpckt; + + } + } + } + } + } + } + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_ABSENT_INFORMATION); + return rpckt; + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED); + return rpckt; + + } + + /** + * Create a hash map that stores objects for quick retrieval later + * @return A hashmap of objects + */ + private HashMap generateObjectHashmap(){ + HashMap objectMap = new HashMap(); + return objectMap; + + } + + + /** + * Given an objectID, return the object associated with it. Check the cache first. + * @param objectID The unique ID of the object + * @return The DTFJ JavaObject + */ + private JavaObject getObject(long objectID){ + if (objectMap == null){ + this.objectMap = generateObjectHashmap(); + } + JavaObject tmpObj = objectMap.get(objectID); + if (tmpObj == null){ + //Last ditch attempt to try and get object + //Sometimes an object is really a class. + try{ + if (isClass(objectID)){ + logr.logError(JDILogger.LEVEL_VERBOSE, " Object is really a class"); //$NON-NLS-1$ + return getClass(objectID).getObject(); + } + }catch(Exception exxy){} + tmpObj = getSlowObject(objectID); + if (tmpObj != null){ + objectMap.put(tmpObj.getID().getAddress(), tmpObj); + }else{ + logr.logError(JDILogger.LEVEL_VERBOSE, " Error finding object " + objectID); //$NON-NLS-1$ + } + + } + return tmpObj; + } + + /** + * Get the object associated with the ID + * @param objectID The unique ID for that object + * @return + */ + private JavaObject getSlowObject(long objectID){ + Iterator asIt = image.getAddressSpaces( ); + while ( asIt.hasNext( ) ) + { + ImageAddressSpace as = (ImageAddressSpace) asIt.next( ); + Iterator prIt = as.getProcesses( ); + while ( prIt.hasNext( ) ){ + ImageProcess process = (ImageProcess) prIt.next( ); + + Iterator runTimesIt = process.getRuntimes( ); + while ( runTimesIt.hasNext( ) ) + { + JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( ); + Iterator heapList = javaRT.getHeaps(); + + while (heapList.hasNext()){ + JavaHeap heap = (JavaHeap) heapList.next(); + Iterator objectList = heap.getObjects(); + while (objectList.hasNext()){ + JavaObject jObject = (JavaObject)objectList.next(); + if (jObject.getID().getAddress() == objectID){ + return jObject; + } + } + } + + } + } + } + return null; + } + + /** + * Given a the name for a class, iterate through all the classes + * @param name The name of the class to search + * @return The DTFJ JavaClass result + * @throws Exception + */ + private JavaClass findClassByName(String name) throws Exception{ + Iterator jClasses = classes.values().iterator(); + while(jClasses.hasNext()){ + JavaClass jClass = jClasses.next(); + if (name.equalsIgnoreCase(jClass.getName())){ + return jClass; + } + } + return null; + } + + /** + * Take care of the objectReference command set of the JDWP specs. + * @param cpckt The incoming command packet request + * @return The reply packet to be returned to the client + * @throws Exception + */ + + private ReplyPacket objectReference(CommandPacket cpckt) throws Exception{ + + if (cpckt.getCommand() == 1){ + //ReferenceType + //Return the ID (reference) of the object's class and type + byte [] inData = cpckt.getByteData(); + long object = createLongFromBytes(inData, 0, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "ObjectReference.ReferenceType(" + object + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + + //Search inside hashmap first + if (objectMap.containsKey(object)){ + JavaObject jObject = getObject(object); + if (jObject != null){ + try{ + int refTypeTag = 1; + + JavaClass jClass = jObject.getJavaClass(); + if (jClass == null){ + + Vector vctr = new Vector(); + vctr.add((byte)1); + JavaClass jOutClass = findClassByName("java/lang/Object"); //$NON-NLS-1$ + + addLongToVector(vctr, jOutClass.getID().getAddress()); + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + logr.logError(JDILogger.LEVEL_VERYVERBOSE, " Cannot get class type"); //$NON-NLS-1$ + return rpckt; + } + long typeID = jObject.getJavaClass().getID().getAddress(); + if (!classes.containsKey(typeID)){ + logr.log(JDILogger.LEVEL_VERYVERBOSE, " Client may not have classID"); //$NON-NLS-1$ + } + logr.log(JDILogger.LEVEL_VERYVERBOSE, " refTagType " + refTypeTag); //$NON-NLS-1$ + logr.log(JDILogger.LEVEL_VERYVERBOSE, " name " + jObject.getJavaClass().getName() + "{"+jObject.getJavaClass().getID().getAddress()+"}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + if (jObject.isArray()){ + refTypeTag = 3; + }else if(isInterface(typeID)){ + refTypeTag = 2; + } + + Vector vctr = new Vector(); + vctr.add((byte)refTypeTag); + addLongToVector(vctr, typeID); + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + }catch(CorruptDataException exxy){ + logr.logError(JDILogger.LEVEL_VERBOSE, " Corrupt data!"); //$NON-NLS-1$ + Vector vctr = new Vector(); + vctr.add((byte)1); + JavaClass jClass = findClassByName("java/lang/Object"); //$NON-NLS-1$ + + addLongToVector(vctr, jClass.getID().getAddress()); + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + exxy.printStackTrace(new PrintStream(logr.getErrorStream())); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + + } + } + }else{ + + JavaClass javaClass = getClass(object); + if (javaClass != null){ + int refTypeTag = 1; + long typeID = javaClass.getID().getAddress(); + + Vector vctr = new Vector(); + vctr.add((byte)refTypeTag); + addLongToVector(vctr, typeID); + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + } + } + + logr.log(JDILogger.LEVEL_VERYVERBOSE, "No matches"); //$NON-NLS-1$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT); + return rpckt; + }else if (cpckt.getCommand() == 2){ + byte [] inData = cpckt.getByteData(); + long object = createLongFromBytes(inData, 0, 8); + int fields = createIntFromBytes(inData, 8, 4); + logr.log(JDILogger.LEVEL_VERBOSE, "ObjectReference.GetValues(" + object + "," + fields + ",...)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + Vector vctr = new Vector(); + addIntToVector(vctr, fields); + for (int i = 0; i < fields; i++){ + long fieldID = createLongFromBytes(inData, 12 + (8*i), 8); + if (objectMap.containsKey(object)){ + logr.log(JDILogger.LEVEL_VERYVERBOSE, " O:" + fieldID); //$NON-NLS-1$ + if (!getFieldFromObject(vctr, object, fieldID)){ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT); + return rpckt; + + } + + }else{ + logr.log(JDILogger.LEVEL_VERYVERBOSE, " C:" + fieldID); //$NON-NLS-1$ + if (!getFieldFromClass(vctr, object, fieldID)){ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT); + return rpckt; + } + } + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + + }else if (cpckt.getCommand() == 6){ + byte [] inData = cpckt.getByteData(); + long object = createLongFromBytes(inData, 0, 8); + long thread = createLongFromBytes(inData, 8, 8); + long clazz = createLongFromBytes(inData, 16, 8); + long method = createLongFromBytes(inData, 24, 8); + int arguments = createIntFromBytes(inData, 32, 4); + Vector vctr = new Vector(); + logr.log(JDILogger.LEVEL_VERBOSE, "ObjectReference.InvokeMethod(" + object + "," + thread + ","+clazz+","+method+","+arguments+",...)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ + if (!isClass(object)){ + JavaObject jObject = getObject(object); + if (jObject != null){ + // + JavaClass jClass = jObject.getJavaClass(); + logr.log(JDILogger.LEVEL_VERYVERBOSE, " object: " + jClass.getName() + ">>" + jObject.getJavaClass().getName()); //$NON-NLS-1$ //$NON-NLS-2$ + vctr.add((byte)'s'); + this.vctrs.put(jObject.getID().getAddress(), jObject.getJavaClass().getName()); + addLongToVector(vctr, jObject.getID().getAddress()); + vctr.add((byte)0); + } + + }else{ + + JavaClass javaClass = getClass(clazz); + if (javaClass != null){ + logr.log(JDILogger.LEVEL_VERYVERBOSE, " class: " + javaClass.getName()); //$NON-NLS-1$ + + vctr.add((byte)'s'); + + this.vctrs.put(javaClass.getID().getAddress(), javaClass.getName()); + addLongToVector(vctr, javaClass.getID().getAddress()); + vctr.add((byte)0); + + } + + + } + if (vctr.size() > 0){ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + } + + + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT); + return rpckt; + + + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED); + return rpckt; + + + } + + /** + * Take care of the strignReference command set of the JDWP specs. + * @param cpckt The incoming command packet request + * @return The reply packet to be returned to the client + * @throws Exception + */ + + private ReplyPacket stringReference(CommandPacket cpckt) throws Exception{ + + if (cpckt.getCommand() == 1){ + byte[] inData = cpckt.getByteData(); + long stringObject = createLongFromBytes(inData, 0, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "StringReference.Value("+stringObject+")"); //$NON-NLS-1$ //$NON-NLS-2$ + if (vctrs.containsKey(stringObject)){ + Vector vctr = new Vector(); + //Truncate down to int, and hope we don't have more than 2^32-1 objects + addStringToVector(vctr, vctrs.get(stringObject)); + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT); + return rpckt; + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED); + return rpckt; + + } + + private ReplyPacket threadReference(CommandPacket cpckt) throws Exception{ + if (cpckt.getCommand() == 1){ + //Lets name a thread! + byte[] inData = cpckt.getByteData(); + long thread = createLongFromBytes(inData, 0, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "ThreadReference.Name(" + thread + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + Iterator asIt = image.getAddressSpaces( ); + while ( asIt.hasNext( ) ) + { + ImageAddressSpace as = (ImageAddressSpace) asIt.next( ); + Iterator prIt = as.getProcesses( ); + + while ( prIt.hasNext( ) ) + { + ImageProcess process = (ImageProcess) prIt.next( ); + Iterator runTimesIt = process.getRuntimes( ); + while ( runTimesIt.hasNext( ) ) + { + JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( ); + Iterator thds = javaRT.getThreads(); + + int count = 0; + while(thds.hasNext()){ + Object tmpobj = thds.next(); + if (tmpobj instanceof CorruptData){ + //ignore this thread + }else{ + count++; + JavaThread thd = (JavaThread)tmpobj; + if (thread == thd.getObject().getID().getAddress()){ + Vector vctr = new Vector(); + addStringToVector(vctr, thd.getName()); + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + } + } + } + } + } + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_THREAD); + return rpckt; + }else if (cpckt.getCommand() == 2){ + logr.log(JDILogger.LEVEL_VERBOSE, "Suspend()"); //$NON-NLS-1$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + return rpckt; + }else if (cpckt.getCommand() == 3){ + logr.log(JDILogger.LEVEL_VERBOSE, "Resume()"); //$NON-NLS-1$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + return rpckt; + }else if (cpckt.getCommand() == 4){ + byte []inData = cpckt.getByteData(); + long thread = createLongFromBytes(inData, 0, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "Status("+thread+")"); //$NON-NLS-1$ //$NON-NLS-2$ + Iterator asIt = image.getAddressSpaces( ); + while ( asIt.hasNext( ) ) + { + ImageAddressSpace as = (ImageAddressSpace) asIt.next( ); + Iterator prIt = as.getProcesses( ); + + while ( prIt.hasNext( ) ) + { + ImageProcess process = (ImageProcess) prIt.next( ); + Iterator runTimesIt = process.getRuntimes( ); + while ( runTimesIt.hasNext( ) ) + { + JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( ); + Iterator thds = javaRT.getThreads(); + Vector vctr = new Vector(); + while(thds.hasNext()){ + Object tmpobj = thds.next(); + if (tmpobj instanceof CorruptData){ + //ignore this thread + }else{ + JavaThread thd = (JavaThread) tmpobj; + if (thd.getObject().getID().getAddress() == thread){ + int threadStatus = 1; + + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread Status: "+thd.getState()); //$NON-NLS-1$ + logr.log(JDILogger.LEVEL_VERYVERBOSE, " Thread Name: " + thd.getName()); //$NON-NLS-1$ + if ((thd.getState() & JavaThread.STATE_TERMINATED) > 0){ + threadStatus = 0; + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is terminated"); //$NON-NLS-1$ + }else if ((thd.getState() & JavaThread.STATE_SLEEPING) > 0){ + threadStatus = 2; + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is sleeping"); //$NON-NLS-1$ + }else if ((thd.getState() & JavaThread.STATE_IN_OBJECT_WAIT) > 0 || (thd.getState() & JavaThread.STATE_WAITING) > 0 || (thd.getState() & JavaThread.STATE_WAITING_INDEFINITELY) > 0 || (thd.getState() & JavaThread.STATE_WAITING_WITH_TIMEOUT) > 0){ + threadStatus = 4; + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is waiting"); //$NON-NLS-1$ + }else if ((thd.getState() & JavaThread.STATE_BLOCKED_ON_MONITOR_ENTER) > 0){ + threadStatus = 3; + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is monitor"); //$NON-NLS-1$ + }else{ + threadStatus = 1; + logr.log(JDILogger.LEVEL_VERBOSE, "Thread is other (running)"); //$NON-NLS-1$ + if ((thd.getState() & JavaThread.STATE_ALIVE) > 0){ + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is alive"); //$NON-NLS-1$ + } + if ((thd.getState() & JavaThread.STATE_IN_NATIVE) > 0){ + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is in native"); //$NON-NLS-1$ + } + if ((thd.getState() & JavaThread.STATE_PARKED) > 0){ + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is parked"); //$NON-NLS-1$ + } + if ((thd.getState() & JavaThread.STATE_INTERRUPTED) > 0){ + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is interrupted"); //$NON-NLS-1$ + } + if ((thd.getState() & JavaThread.STATE_VENDOR_1) > 0){ + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is vendor 1"); //$NON-NLS-1$ + } + if ((thd.getState() & JavaThread.STATE_VENDOR_3) > 0){ + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is vendor 2"); //$NON-NLS-1$ + } + if ((thd.getState() & JavaThread.STATE_VENDOR_2) > 0){ + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is vendor 3"); //$NON-NLS-1$ + } + if ((thd.getState() & JavaThread.STATE_RUNNABLE) > 0){ + logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is runnable"); //$NON-NLS-1$ + } + + + } + //The thread always starts in Eclipse as running + //Even if it isn't (See bug #161781) + int suspendStatus = 1; + threadStatus = 2; + addIntToVector(vctr, threadStatus); + addIntToVector(vctr, suspendStatus); + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + + } + } + + } + + + + } + + } + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT); + return rpckt; + }else if (cpckt.getCommand() == 5){ + + //ThreadGroup + //This call returns the group of the input thread. + //TODO - Since this doesn't seem available in DTFJ, let's fake it with 0 + byte [] inData = cpckt.getByteData(); + long thread = createLongFromBytes(inData, 0, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "ThreadGroup("+thread+")"); //$NON-NLS-1$ //$NON-NLS-2$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + Vector vctr = new Vector(); + addLongToVector(vctr, 0); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + }else if (cpckt.getCommand() == 6){ + //List all the frames from the thread + + byte []inData = cpckt.getByteData(); + long thread = createLongFromBytes(inData, 0, 8); + int startFrame = createIntFromBytes(inData, 8, 4); + int length = createIntFromBytes(inData, 12, 4); + logr.log(JDILogger.LEVEL_VERBOSE, "Frames(" + thread + "," + startFrame + "," + length + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + + Iterator asIt = image.getAddressSpaces( ); + while ( asIt.hasNext( ) ) + { + ImageAddressSpace as = (ImageAddressSpace) asIt.next( ); + Iterator prIt = as.getProcesses( ); + + while ( prIt.hasNext( ) ) + { + ImageProcess process = (ImageProcess) prIt.next( ); + Iterator runTimesIt = process.getRuntimes( ); + while ( runTimesIt.hasNext( ) ) + { + JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( ); + Iterator thds = javaRT.getThreads(); + while(thds.hasNext()){ + Object tmpobj = thds.next(); + if (tmpobj instanceof CorruptData){ + //ignore this thread + }else{ + JavaThread thd = (JavaThread) tmpobj; + if (thd.getObject().getID().getAddress() == thread){ + int currentFrame = 0; + int count = 0; + Iterator frames = thd.getStackFrames(); + Vector vctr = new Vector(); + int count2 = 0; + while(frames.hasNext()){ + count2++; + if (length > 0){ + if (currentFrame >= startFrame && currentFrame <= startFrame + length){ + JavaStackFrame jStackFrame = (JavaStackFrame)frames.next(); + addLongToVector(vctr, jStackFrame.getBasePointer().getAddress()); + + JavaLocation jLoc = jStackFrame.getLocation(); + + JavaMethod jMethod = jLoc.getMethod(); + + JavaClass jClass = jMethod.getDeclaringClass(); + + if (jClass.isArray()){ + vctr.add((byte)3); + }else if(isInterface(jClass.getID().getAddress())){ + vctr.add((byte)2); + }else{ + vctr.add((byte)1); + } + + addLongToVector(vctr, jClass.getID().getAddress()); + addLongToVector(vctr, getMethodId(jClass.getID().getAddress(), jMethod)); + + //This is the current memory address. + addLongToVector(vctr, jLoc.getAddress().getAddress()); + try{ + logr.log(JDILogger.LEVEL_VERYVERBOSE, " " + jLoc.getFilename() + "@" + jLoc.getMethod().getDeclaringClass().getName() + "{"+jLoc.getMethod().getDeclaringClass().getID().getAddress()+"}." + jLoc.getMethod().getName() + "{"+getMethodId(jClass.getID().getAddress(), jLoc.getMethod())+"}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ + try{ + logr.log(JDILogger.LEVEL_VERYVERBOSE, " :" + jLoc.getLineNumber()); //$NON-NLS-1$ + }catch(Exception exxy){ + } + + }catch (Exception exxy){} + count++; + } + }else{ + if (currentFrame >= startFrame){ + JavaStackFrame jStackFrame = (JavaStackFrame)frames.next(); + addLongToVector(vctr, jStackFrame.getBasePointer().getAddress()); + + JavaLocation jLoc = jStackFrame.getLocation(); + + JavaMethod jMethod = jLoc.getMethod(); + + JavaClass jClass = jMethod.getDeclaringClass(); + if (jClass.isArray()){ + vctr.add((byte)3); + }else if(isInterface(jClass.getID().getAddress())){ + vctr.add((byte)2); + }else{ + vctr.add((byte)1); + } + + addLongToVector(vctr, jClass.getID().getAddress()); + addLongToVector(vctr, getMethodId(jClass.getID().getAddress(), jMethod)); + + //Location is 8 bytes (2 ints) + //We pad with 4 bytes of zeros + try{ + addLongToVector(vctr, jLoc.getLineNumber()); + } + catch(Exception exxy){ + addLongToVector(vctr, -1); + } + try{ + logr.log(JDILogger.LEVEL_VERYVERBOSE, " " + jLoc.getFilename() + "@" + jLoc.getMethod().getDeclaringClass().getName() + "{"+jLoc.getMethod().getDeclaringClass().getID().getAddress()+"}." + jLoc.getMethod().getName() + "{"+getMethodId(jClass.getID().getAddress(),jLoc.getMethod())+"}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ + try{ + logr.log(JDILogger.LEVEL_VERYVERBOSE, " :" + jLoc.getLineNumber()); //$NON-NLS-1$ + }catch(Exception exxy){ + } + + }catch (Exception exxy){} + + count++; + } + } + } + logr.log(JDILogger.LEVEL_VERYVERBOSE, count + " frames found (of " +count2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE); + addIntToVectorFront(vctr, count); + rpckt.setData(vectorToByte(vctr)); + return rpckt; + + } + } + } + } + } + } + ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT); + return rpckt; + }else if (cpckt.getCommand() == 7){ + //List all the frames from the thread + + byte []inData = cpckt.getByteData(); + long thread = createLongFromBytes(inData, 0, 8); + logr.log(JDILogger.LEVEL_VERBOSE, "FrameCount(" + thread + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + + Iterator asIt = image.getAddressSpaces( ); + while ( asIt.hasNext( ) ) + { + ImageAddressSpace as = (ImageAddressSpace) asIt.next( ); + Iterator prIt = as.getProcesses( ); + + while ( prIt.hasNext( ) ) + { + ImageProcess process = (ImageProcess) prIt.next( ); + Iterator runTimesIt = process.getRuntimes( ); + while ( runTimesIt.hasNext( ) ) + { + JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( ); + Iterator thds = javaRT.getThreads(); + while(thds.hasNext()){ + Object tmpobj = thds.next(); + if (tmpobj instanceof CorruptData){ + //ignore this thread + }else{ + JavaThread thd = (JavaThread) tmpobj; [... 425 lines stripped ...]