/*******************************************************************************
* 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.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.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.logging.Level;
import javax.tools.diagnostics.FactoryRegistry;
import javax.tools.diagnostics.image.CorruptData;
import javax.tools.diagnostics.image.CorruptDataException;
import javax.tools.diagnostics.image.DataUnavailable;
import javax.tools.diagnostics.image.DiagnosticException;
import javax.tools.diagnostics.image.Image;
import javax.tools.diagnostics.image.ImageAddressSpace;
import javax.tools.diagnostics.image.ImageProcess;
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.JavaLocation;
import javax.tools.diagnostics.runtime.java.JavaMethod;
import javax.tools.diagnostics.runtime.java.JavaMonitor;
import javax.tools.diagnostics.runtime.java.JavaObject;
import javax.tools.diagnostics.runtime.java.JavaRuntime;
import javax.tools.diagnostics.runtime.java.JavaStackFrame;
import javax.tools.diagnostics.runtime.java.JavaThread;
import javax.tools.diagnostics.runtime.java.JavaVariable;
/**
* KatoReader
*
* KatoReader is our second conversion layer (after JDWPServer). KatoReader has two functions:
* <ol>
* <li> Convert JDWP <--> Kato</li>
* <li> Provide several convenience methods </li>
* </ol>
*
* <ol>
* <li>
* <p>
* KatoReader 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 KatoReader 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.
* </p>
* <br/>
* <p>
* 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.
* </p>
* </li>
* <li>
* We provide bytes <--> int, bytes <--> long, vector --> byte[], and a few other assorted
* methods for doing standard stuff.
* </li>
* </ol>
*
*/
public class KatoReader implements CacherProvider{
private HashMap<Long, JavaClass> 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<Long,String> 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<Integer, JavaMethod> intToMethod;
private HashMap<JavaMethod, Integer> methodToInt;
private Vector<JavaField> 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_CLASS = 21;
public static final int ERROR_INVALID_THREAD = 10;
public static final int ERROR_INVALID_SLOT = 35;
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;
public static final int INVALID_EVENT_TYPE = 102;
private HashMap<Long, JavaObject> objectMap;
private HashMap<Long, JavaMonitor> monitorMap;
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 static final int TAG_ARRAY = 91;
public static final int TAG_BYTE = 66;
public static final int TAG_CHAR = 67;
public static final int TAG_OBJECT = 76;
public static final int TAG_FLOAT = 70;
public static final int TAG_DOUBLE = 68;
public static final int TAG_INT = 73;
public static final int TAG_LONG = 74;
public static final int TAG_SHORT = 83;
public static final int TAG_VOID = 86;
public static final int TAG_BOOLEAN = 90;
public static final int TAG_STRING = 115;
public static final int TAG_THREAD = 116;
public static final int TAG_THREAD_GROUP = 103;
public static final int TAG_CLASS_LOADER = 108;
public static final int TAG_CLASS_OBJECT = 99;
public KatoReader(){
}
/**
* Constructor to init Kato 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 Kato api, or sanity test fail
*/
public KatoReader(String ipathToCore, JDWPServer isvr, JDILogger logger) throws Exception{
logr = logger;
logr.log(JDILogger.LEVEL_VERYVERBOSE, "KatoReader 1.0"); //$NON-NLS-1$
pathToCore = ipathToCore;
svr = isvr;
vctrs = new HashMap<Long, String>();
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Starting to read core file"); //$NON-NLS-1$
startRead();
}
/**
* Given a Kato 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 Kato calls fail
*/
private boolean getValueFromField(Vector<Byte> 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{
Object field = jField.get(jObject);
if(field instanceof JavaObject){
JavaObject jOut = (JavaObject)field;
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 " + ((field == null) ? "null" : field.getClass().getName())); //$NON-NLS-1$
}
}
catch(NullPointerException exxy){
logr.logError(JDILogger.LEVEL_VERYVERBOSE, " Attemped access to field is null"); //$NON-NLS-1$
addLongToVector(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);
case COMMANDSET_CLASS_LOADER_REFERENCE:
return classLoaderRef(cpckt);
// Added for jdb
case COMMANDSET_THREAD_GROUP_REFERENCE:
return threadGroupReference(cpckt);
default:
logr.logError(JDILogger.LEVEL_VERBOSE, "Unknown command set: "+cpckt.getCommandSet()); //$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 {
FactoryRegistry registry=null;
registry=FactoryRegistry.getDefaultRegistry();
image = registry.getImage(f);
} 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$
this.monitorMap = buildMonitors();
buildMethods();
}
/**
* Get the method object given a methodID
* @param methodID Address of the method as stored in the vector
* @return The Kato 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 Kato JavaField
*/
private JavaField getField(long fieldID){
if (fieldList == null){
fieldList = buildFields();
}
return fieldList.elementAt((int)fieldID);
}
private HashMap<Long, JavaMonitor> buildMonitors(){
HashMap<Long, JavaMonitor> monitors = new HashMap<Long, JavaMonitor>();
Iterator asIt = image.getAddressSpaces( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) ){
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
List<JavaMonitor> jms = javaRT.getMonitors();
for (JavaMonitor jm: jms){
monitors.put(jm.getObject().getID().getAddress(), jm);
}
}
}
}
return monitors;
}
/**
* Build the field vector by going through all the classes
* @return A vector containing a list of JDIJavaFields
*/
private Vector<JavaField> buildFields(){
Vector<JavaField> fieldList = new Vector<JavaField>();
Iterator<JavaClass> 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().iterator();
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<Integer, JavaMethod>();
methodToInt = new HashMap<JavaMethod, Integer>();
Iterator<JavaClass> 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().iterator();
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 Kato 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 Kato 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<Byte> 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<Byte> 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<Long, JavaClass> buildClasses() {
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Building class list"); //$NON-NLS-1$
HashMap<Long, JavaClass> classes = new HashMap<Long, JavaClass>();
Iterator asIt = image.getAddressSpaces( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) ){
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
Iterator classLoaders = javaRT.getJavaClassLoaders().iterator();
while (classLoaders.hasNext()){
JavaClassLoader javaCL = (JavaClassLoader)classLoaders.next();
Iterator javaClasses = javaCL.getDefinedClasses().iterator();
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;
}
/**
* Transforms a JavaObject into a real java/lang/String object.
* Does this by extracting the following fields from java/lang/String:
* <pre>
* int offset, count;
* char[] value;
* </pre>
*
* @param object
* JavaObject representation of a java.lang.String object.
* @return String or null if there were problems.
* @throws IllegalArgumentException thrown if JavaObject not java/lang/String
*/
public static String javaObjectToString(JavaObject object)
throws IllegalArgumentException {
if (object == null) {
return null;
}
String className = null;
JavaClass stringClass = null;
try {
stringClass = object.getJavaClass();
className = stringClass.getName();
} catch (CorruptDataException e) {
e.printStackTrace();
return null;
}
if (!className.equals("java/lang/String")) {
throw new IllegalArgumentException(
"Mismatched types - expecting java/lang/String, got `"
+ className + "'");
}
int offset = 0, count = 0;
char[] value = null;
JavaObject valueArray = null;
boolean gotValue = false, gotOffset = false, gotCount = false;
// Get all fields, pick out interesting ones.
for (Object fobj : stringClass.getDeclaredFields()) {
if (fobj instanceof CorruptData) {
continue;
}
JavaField field = (JavaField) fobj;
try {
String fieldName = field.getName();
if (fieldName.equals("offset")) {
offset = field.getInt(object);
gotOffset = true;
} else if (fieldName.equals("count")) {
count = field.getInt(object);
gotCount = true;
} else if (fieldName.equals("value")) {
valueArray = (JavaObject) field.get(object);
gotValue = true;
}
} catch (DiagnosticException e) {
e.printStackTrace();
return null;
}
}
try {
// Check we got all of the fields.
if ((gotOffset || gotCount || gotValue) == false) {
return null;
} else {
int length = (int) valueArray.getArraySize();
value = new char[length];
try {
valueArray.arraycopy(0, value, 0, length);
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
return null;
}
}
return new String(value, offset, count);
} catch (CorruptDataException e) {
e.printStackTrace();
return null;
} catch (MemoryAccessException e) {
e.printStackTrace();
return null;
}
}
/**
* 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<Byte> 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<Byte> 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<Byte> 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<Byte> 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 16bit short to the front of the Byte Vector
* @param vctr Vector to add the bytes to
* @param inShort The short to add
*/
public static void addShortToVectorFront(Vector<Byte> vctr, short inShort){
vctr.add(0, getByteFromInt(inShort, 1));
vctr.add(1, getByteFromInt(inShort, 0));
}
/**
* Add a 16bit short to the end of the Byte Vector
* @param vctr Vector to add the bytes to
* @param inShort The int to add
*/
public static void addShortToVector(Vector<Byte> vctr, int inShort){
vctr.add(getByteFromInt(inShort, 1));
vctr.add(getByteFromInt(inShort, 0));
}
/**
* Add a 16bit char to the front of the Byte Vector
* @param vctr Vector to add the bytes to
* @param inChar The short to add
*/
public static void addCharToVectorFront(Vector<Byte> vctr, int inChar){
vctr.add(0, getByteFromInt(inChar, 1));
vctr.add(1, getByteFromInt(inChar, 0));
}
/**
* Add a 16bit char to the end of the Byte Vector
* @param vctr Vector to add the bytes to
* @param inChar The int to add
*/
public static void addCharToVector(Vector<Byte> vctr, int inChar){
vctr.add(getByteFromInt(inChar, 1));
vctr.add(getByteFromInt(inChar, 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<Byte> 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 Kato JavaClass
* @param classID The unique class ID
* @return The Kato JavaClass
* @throws CorruptDataException
*/
private JavaClass getClass(long classID){
if (classes == null){
classes = buildClasses();
}
JavaClass jcl = classes.get(classID);
if (jcl == null){
/**
* Attemp to get directly, useful for system class loader which isn't covered
* by build classes as it is not part of the class loader loaded classes.
*/
}
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( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) )
{
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
Iterator thds = javaRT.getThreads().iterator();
while(thds.hasNext()){
Object tmpobj = thds.next();
if (tmpobj instanceof CorruptData){
//ignore this thread
}else{
JavaThread thd = (JavaThread) tmpobj;
Iterator frames = thd.getStackFrames().iterator();
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( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) )
{
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
Iterator thds = javaRT.getThreads().iterator();
while(thds.hasNext()){
Object tmpobj = thds.next();
if (tmpobj instanceof CorruptData){
//ignore this thread
}else{
JavaThread thd = (JavaThread) tmpobj;
Iterator frames = thd.getStackFrames().iterator();
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( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) ){
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
//Since there doesn't seem to be a matching Kato 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<Byte> vctr = new Vector<Byte>();
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_CLASS_PATHS){
logr.log(JDILogger.LEVEL_VERYVERBOSE, "This does not return the actual class path, simply allows JDB to work.");
Vector<Byte> vctr = new Vector<Byte>();
addStringToVector(vctr, "");
addIntToVector(vctr, 0);
addIntToVector(vctr, 0);
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
rpckt.setData(vectorToByte(vctr));
return rpckt;
} else if (cpckt.getCommand() == VIRTUAL_MACHINE_CLASSES_BY_SIGNATURE){
Vector<Byte> vctr = new Vector<Byte>();
byte []inData = cpckt.getByteData();
String signature = getStringFromBytes(inData, 0);
if (signature.charAt(0) == 'L'){
signature = signature.substring(1, signature.length() - 1);
}
logr.log(JDILogger.LEVEL_VERBOSE, "ClassesBySignature(" + signature + ")"); //$NON-NLS-1$ //$NON-NLS-2$
int count = 0;
Iterator <JavaClass> javaClasses = classes.values().iterator();
while (javaClasses.hasNext()){
JavaClass javaClass = javaClasses.next();
String searched = javaClass.getName();
if (searched.equals(signature)){
count++;
if (javaClass.isArray()){
vctr.add((byte)3);
}else if (isInterface(javaClass.getID().getAddress())){
vctr.add((byte)2);
}else{
vctr.add((byte)1);
}
//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() +" " + Long.toHexString(javaClass.getID().getAddress())); //$NON-NLS-1$
}else{
String mangledName = "" + searched + ""; //$NON-NLS-1$ //$NON-NLS-2$
if (mangledName.equals(signature)){
count++;
if (javaClass.isArray()){
vctr.add((byte)3);
}else if (isInterface(javaClass.getID().getAddress())){
vctr.add((byte)2);
}else{
vctr.add((byte)1);
}
//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++;
if (javaClass.isArray()){
vctr.add((byte)3);
}else if (isInterface(javaClass.getID().getAddress())){
vctr.add((byte)2);
}else{
vctr.add((byte)1);
}
//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);
logr.log(JDILogger.LEVEL_VERYVERBOSE, count+" matches"); //$NON-NLS-1$
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<Byte> vctr = new Vector<Byte>();
int count = 0;
Iterator <JavaClass> 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 = "" + 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( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) )
{
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
Iterator thds = javaRT.getThreads().iterator();
Vector<Byte> vctr = new Vector<Byte>();
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_TOP_LEVEL_THREAD_GROUPS){
// return an arbitrary thread group name, return all of them in a single group.
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
Vector<Byte> vctr = new Vector<Byte>();
addIntToVector(vctr, 1);
addLongToVector(vctr, 1);
byte []barray = vectorToByte(vctr);
rpckt.setData(barray);
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<Byte> vctr = new Vector<Byte>();
//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){
shutDownKato();
//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_CREATE_STRING){
Vector<Byte> vctr = new Vector<Byte>();
addLongToVector(vctr, 0);
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}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 = 1;
byte canGetCurrentContendedMonitor = 1;
byte canGetMonitorInfo = 1;
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<Byte> vctr = new Vector<Byte>();
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;
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
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<Byte> vctr = new Vector<Byte>();
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){
if (javaClass.isArray()){
logr.log(JDILogger.LEVEL_VERYVERBOSE, "" + javaClass.getName() + ""); //$NON-NLS-1$ //$NON-NLS-2$
addStringToVector(vctr, "" + javaClass.getName() + ""); //$NON-NLS-1$ //$NON-NLS-2$
}else{
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<Byte> vctr = new Vector<Byte>();
JavaObject obj = javaClass.getClassLoader().getObject();
long address = 0L;
if (obj != null) {
address = obj.getID().getAddress();
}
addLongToVector(vctr, address);
logr.log(JDILogger.LEVEL_VERYVERBOSE, " 0x" + Long.toHexString(address) ); //$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<Byte> vctr = new Vector<Byte>();
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().iterator();
logr.log(JDILogger.LEVEL_VERYVERBOSE, javaClass.getName() + ":"); //$NON-NLS-1$
Vector<Byte> vctr = new Vector<Byte>();
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().iterator();
logr.log(JDILogger.LEVEL_VERYVERBOSE, javaClass.getName() + ":"); //$NON-NLS-1$
Vector<Byte> vctr = new Vector<Byte>();
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<Byte> vctr = new Vector<Byte>();
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( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) )
{
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
Iterator thds = javaRT.getThreads().iterator();
while(thds.hasNext()){
Object tmpobj = thds.next();
if (tmpobj instanceof CorruptData){
//ignore this thread
}else{
JavaThread thd = (JavaThread) tmpobj;
Iterator frames = thd.getStackFrames().iterator();
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<Byte> vctr = new Vector<Byte>();
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){
logr.log(JDILogger.LEVEL_VERYVERBOSE, " Missing source file name information"); //$NON-NLS-1$
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_ABSENT_INFORMATION);
return rpckt;
}
}
}
}
}
}
}
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, " Not on stack, cannot retrieve information"); //$NON-NLS-1$
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().iterator();
logr.log(JDILogger.LEVEL_VERYVERBOSE, javaClass.getName() + ":"); //$NON-NLS-1$
Vector<Byte> vctr = new Vector<Byte>();
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_CLASS_OBJECT){
// Simply returns null for class object, jdb compatability
byte []inData = cpckt.getByteData();
long refType = createLongFromBytes(inData, 0, 8);
logr.log(JDILogger.LEVEL_VERYVERBOSE, "ObjectClass");
Vector<Byte> vctr = new Vector<Byte>();
addLongToVector(vctr, 0);
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
rpckt.setData(vectorToByte(vctr));
}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<Byte> vctr = new Vector<Byte>();
addStringToVector(vctr, ""); //$NON-NLS-1$
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
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<Byte> vctr = new Vector<Byte>();
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){
JavaClass jSuperClass = javaClass.getSuperclass();
if( jSuperClass != null) {
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;
} else {
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;
}
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Invalid class ID"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
} else if (cpckt.getCommand() == 3){
Vector<Byte> vctr = new Vector<Byte>();
byte []inData = cpckt.getByteData();
long classID = createLongFromBytes(inData, 0, 8);
logr.log(JDILogger.LEVEL_VERYVERBOSE,"Tried to invoke static method! "+classID);
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
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( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) )
{
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
Iterator thds = javaRT.getThreads().iterator();
while(thds.hasNext()){
Object tmpobj = thds.next();
if (tmpobj instanceof CorruptData){
//ignore this thread
}else{
JavaThread thd = (JavaThread) tmpobj;
Iterator frames = thd.getStackFrames().iterator();
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<Byte> vctr = new Vector<Byte>();
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);
// }
//Code index start
addLongToVector(vctr, 0);
//Code index end
addLongToVector(vctr, 99999999); // TODO go through local variable tables looking for highest reference?
//Number of lines
addIntToVector(vctr, 1);
//for(int i = lowest; i <= highest; i++){
addLongToVector(vctr, jLocation.getAddress().getAddress()-1);
addIntToVector(vctr, jLocation.getLineNumber());
//}
}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, -1);
//Code index end
addLongToVector(vctr, -1);
//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;
}
}
}
}
}
}
}
Vector<Byte> vctr = new Vector<Byte>();
addLongToVector(vctr, -1);
//Code index end
addLongToVector(vctr, -1);
//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;
}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( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) )
{
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
Iterator thds = javaRT.getThreads().iterator();
while(thds.hasNext()){
Object tmpobj = thds.next();
if (tmpobj instanceof CorruptData){
//ignore this thread
}else{
JavaThread thd = (JavaThread) tmpobj;
Iterator frames = thd.getStackFrames().iterator();
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){
Vector<Byte> vctr = new Vector<Byte>();
List vars = jMethod.getVariables();
String sig = jMethod.getSignature();
addIntToVector(vctr, methodSignatureSize(sig));
addIntToVector(vctr, vars.size());
logr.log(JDILogger.LEVEL_VERYVERBOSE, " "+jLocation+
" vars.size="+vars.size());
for (Object nextVar : vars) {
if (nextVar instanceof CorruptData) {
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Corrupt local variable data");
continue;
}
JavaVariable var = (JavaVariable) nextVar;
addLongToVector(vctr, var.getStart());
addStringToVector(vctr, var.getName());
addStringToVector(vctr, var.getSignature());
addIntToVector(vctr, var.getLength());
addIntToVector(vctr, var.getSlot());
logr.log(JDILogger.LEVEL_VERYVERBOSE, " start:"+var.getStart()+
" name:`"+var.getName()+ "'"+
" signature:`"+var.getSignature()+"'"+
" length: "+var.getLength()+
" slot: "+var.getSlot()); //$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_ABSENT_INFORMATION);
return rpckt;
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
return rpckt;
}
/**
* Works out and returns the size of a method's arguments from it's signature.
* doubles and longs and object references are regarded as
*
* @param signature JNI signature of method.
* e.g. "(Ljava/lang/String;LB)I"
* which would be:
* int method(String arg0, long arg1, byte arg2);
*
*
* @return size of arguments
*/
public static int methodSignatureSize(String signature) {
int state = 0;
int size = 0;
LOOP: for (int i=0; i < signature.length(); i++) {
char c = signature.charAt(i);
switch(state) {
case 0: // First character must be a "("
switch(c) {
case '(':
state = 1;
break;
default:
throw new IllegalArgumentException("Bad character `"+c+"' in signature `"+signature+"' in state "+state);
}
break;
case 1: // parse characters
switch(c) {
case 'Z':
case 'B':
case 'S':
case 'C':
case 'I':
case 'F':
size++;
break;
case 'D':
case 'J':
size +=2;
break;
case '[':
size++;
state = 2; // go to parse array state
break;
case 'L':
size++;
state = 3; // go to parse object state
break;
case ')':
state = 4; // go to end state.
break;
default:
throw new IllegalArgumentException("Bad character `"+c+"' in signature `"+signature+"' in state "+state);
}
break;
case 2: // Parse array
switch(c) {
case 'L':
state = 3;
case '[':
// remain in this state
break;
case 'Z':
case 'B':
case 'S':
case 'C':
case 'I':
case 'F':
case 'D':
case 'J':
state = 1; // go back to character parsing state
break;
default:
throw new IllegalArgumentException("Bad character `"+c+"' in signature `"+signature+"' in state "+state);
}
case 3: // Parse object
switch (c) {
case ';':
state = 1; // reached end of object descriptor. stop.
break;
default:
// anything else is fair game.
}
case 4: // end state - return value remains - just ignore characters.
break LOOP; // Exit the loop, we won't parse the return type.
default:
throw new IllegalStateException("In unexpected state "+state+ "in signature `"+signature+"'");
}
}
return size;
}
/**
* Create a hash map that stores objects for quick retrieval later
* @return A hashmap of objects
*/
private HashMap<Long, JavaObject> generateObjectHashmap(){
HashMap<Long, JavaObject> objectMap = new HashMap<Long, JavaObject>();
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 Kato 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( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) ){
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
try {
JavaObject jObject = javaRT.getObjectAtAddress(as.getPointer(objectID));
if (jObject != null){
return jObject;
}
} catch (CorruptDataException e) {
//e.printStackTrace();
} catch (IllegalArgumentException e) {
//e.printStackTrace();
} catch (MemoryAccessException e) {
//e.printStackTrace();
} catch (DataUnavailable e) {
//e.printStackTrace();
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Could not find class directly, searching through heap");
// Old method for returning java objects
Iterator heapList = javaRT.getHeaps().iterator();
while (heapList.hasNext()){
JavaHeap heap = (JavaHeap) heapList.next();
Iterator objectList = heap.getObjects().iterator();
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 Kato JavaClass result
* @throws Exception
*/
private JavaClass findClassByName(String name) throws Exception{
Iterator<JavaClass> 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<Byte> vctr = new Vector<Byte>();
vctr.add((byte)1);
logr.logError(JDILogger.LEVEL_VERYVERBOSE, " Cannot get class type, returning object instead"); //$NON-NLS-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$
}
if (jObject.isArray()){
refTypeTag = 3;
}else if(isInterface(typeID)){
refTypeTag = 2;
}
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$
Vector<Byte> vctr = new Vector<Byte>();
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<Byte> vctr = new Vector<Byte>();
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<Byte> vctr = new Vector<Byte>();
vctr.add((byte)refTypeTag);
addLongToVector(vctr, typeID);
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}
JavaObject jObject = getObject(object);
if (jObject != null){
// This is a copy from above, could be made into a method
try{
int refTypeTag = 1;
JavaClass jClass = jObject.getJavaClass();
if (jClass == null){
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Found the object the slow route");
Vector<Byte> vctr = new Vector<Byte>();
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$
}
if (jObject.isArray()){
refTypeTag = 3;
}else if(isInterface(typeID)){
refTypeTag = 2;
}
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$
Vector<Byte> vctr = new Vector<Byte>();
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<Byte> vctr = new Vector<Byte>();
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;
}
}
}
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<Byte> vctr = new Vector<Byte>();
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)){
logr.log(JDILogger.LEVEL_VERYVERBOSE, " O:" + fieldID+" Invalid Object/Field"); //$NON-NLS-1$
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)){
logr.log(JDILogger.LEVEL_VERYVERBOSE, " O:" + fieldID+" Invalid Object/Field"); //$NON-NLS-1$
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() == 5){
// Monitor information, assume JNIEnv is the same as threadID...
byte[] inData = cpckt.getByteData();
long object = createLongFromBytes(inData, 0, 8);
Vector<Byte> vctr = new Vector<Byte>();
JavaMonitor jm = null;
logr.log(JDILogger.LEVEL_VERBOSE,"ObjectReference.MonitorInfo("+object+")");
if ((jm = monitorMap.get(objectMap))!= null){
JavaThread owningThread = jm.getOwner();
if (owningThread != null){
addLongToVector(vctr, owningThread.getJNIEnv().getAddress());
}else{
addLongToVector(vctr, 0);
}
addIntToVector(vctr, 1);
addIntToVector(vctr, jm.getEnterWaiters().size());
for (JavaThread thr : jm.getEnterWaiters()){
addLongToVector(vctr, thr.getJNIEnv().getAddress());
}
logr.log(JDILogger.LEVEL_VERYVERBOSE," "+jm.getEnterWaiters().size()+" waiting and owner is "+owningThread);
}else{
addLongToVector(vctr, 0);
addIntToVector(vctr, 0);
addIntToVector(vctr, 0);
logr.log(JDILogger.LEVEL_VERYVERBOSE," no monitor information");
}
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<Byte> vctr = new Vector<Byte>();
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;
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Invalid object");
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
return rpckt;
}else if (cpckt.getCommand() == 7){
byte [] inData = cpckt.getByteData();
long object = createLongFromBytes(inData, 0, 8);
JavaObject obj = getObject(object);
logr.log(JDILogger.LEVEL_VERBOSE, "ObjectReference.DisableCollection(" + object + ")"); //$NON-NLS-1$ //$NON-NLS-2$
if (obj != null){
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
return rpckt;
}
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
return rpckt;
}else if (cpckt.getCommand() == 8){
logr.log(JDILogger.LEVEL_VERBOSE, "ObjectReference.EnableCollection(" + ")"); //$NON-NLS-1$ //$NON-NLS-2$
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
return rpckt;
}else if (cpckt.getCommand() == 9){
byte [] inData = cpckt.getByteData();
long object = createLongFromBytes(inData, 0, 8);
logr.log(JDILogger.LEVEL_VERBOSE, "ObjectReference.IsCollected(" + object + ")"); //$NON-NLS-1$ //$NON-NLS-2$
JavaObject obj = getObject(object);
if (obj != null){
Vector<Byte> vctr = new Vector<Byte>();
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_INVALID_OBJECT);
return rpckt;
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
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<Byte> vctr = new Vector<Byte>();
//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;
}else{
// This catches cases where we have not occupied vctrs with a string reference (added to support name labels on arrays of objects)
JavaObject obj = getObject(stringObject);
if (obj != null) {
for (JavaField field : obj.getJavaClass()
.getDeclaredFields()) {
if (field.getSignature().equals("[C")) {
JavaObject stringObj = (JavaObject) field.get(obj);
char charArray[] = new char[stringObj
.getArraySize()];
stringObj.arraycopy(0, charArray, 0, stringObj
.getArraySize());
String stringRef = new String(charArray);
Vector<Byte> vctr = new Vector<Byte>();
addStringToVector(vctr, stringRef);
ReplyPacket rpckt = new ReplyPacket(cpckt
.getSequence(), FLAG_REPLY_PACKET,
ERROR_NONE);
vctrs.put(stringObject, stringRef);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}
}
}
}
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
return rpckt;
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
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( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) )
{
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
Iterator thds = javaRT.getThreads().iterator();
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<Byte> vctr = new Vector<Byte>();
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( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) )
{
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
Iterator thds = javaRT.getThreads().iterator();
Vector<Byte> vctr = new Vector<Byte>();
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 Kato, let's fake it with 0
// Lets fake it with 1 ...
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<Byte> vctr = new Vector<Byte>();
addLongToVector(vctr, 1);
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( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) )
{
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
Iterator thds = javaRT.getThreads().iterator();
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().iterator();
Vector<Byte> vctr = new Vector<Byte>();
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.getAddress().getAddress());
}
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( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) )
{
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
Iterator thds = javaRT.getThreads().iterator();
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 count = 0;
Iterator frames = thd.getStackFrames().iterator();
Vector<Byte> vctr = new Vector<Byte>();
while(frames.hasNext()){
frames.next();
count++;
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, count + " frames found"); //$NON-NLS-1$
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
addIntToVector(vctr, count);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}
}
}
}
}
}
logr.log(JDILogger.LEVEL_VERBOSE, "0 frames and no thread found"); //$NON-NLS-1$
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
return rpckt;
}else if(cpckt.getCommand() == 8){
// Monitor information
byte[] inData = cpckt.getByteData();
long threadID = createLongFromBytes(inData, 0, 8);
logr.log(JDILogger.LEVEL_VERBOSE, "Thread.OwnedMonitors(" + threadID + ")"); //$NON-NLS-1$ //$NON-NLS-2$
List<JavaObject> ownedMonitors = new ArrayList<JavaObject>();
for (JavaMonitor jm : monitorMap.values()){
JavaThread thr;
if ((thr = jm.getOwner())!= null){
if (thr.getJNIEnv().getAddress() == threadID){
ownedMonitors.add(jm.getObject());
}
}
}
Vector<Byte> vctr = new Vector<Byte>();
addIntToVector(vctr, ownedMonitors.size());
for (JavaObject obj: ownedMonitors){
vctr.add((byte)TAG_OBJECT);
addLongToVector(vctr, obj.getID().getAddress());
logr.log(JDILogger.LEVEL_VERYVERBOSE, " Owns "+obj.getID().getAddress()); //$NON-NLS-1$ //$NON-NLS-2$
}
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}else if(cpckt.getCommand() == 9){
// Monitor information
byte[] inData = cpckt.getByteData();
long threadID = createLongFromBytes(inData, 0, 8);
logr.log(JDILogger.LEVEL_VERBOSE, "Thread.CurrentContendedMonitors(" + threadID + ")"); //$NON-NLS-1$ //$NON-NLS-2$
JavaMonitor contended = null;
for (JavaMonitor jm : monitorMap.values()){
for (JavaThread thr: jm.getEnterWaiters()){
if (thr.getJNIEnv().getAddress() == threadID){
contended = jm;
}
}
}
Vector<Byte> vctr = new Vector<Byte>();
if (contended == null){
addLongToVector(vctr, 0);
}else{
addIntToVector(vctr, (byte)TAG_OBJECT);
addLongToVector(vctr, contended.getObject().getID().getAddress());
logr.log(JDILogger.LEVEL_VERYVERBOSE, " Contended on "+contended.getObject().getID().getAddress()); //$NON-NLS-1$ //$NON-NLS-2$
}
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}else if(cpckt.getCommand() == 12){
logr.log(JDILogger.LEVEL_VERBOSE, "SuspendCount()"); //$NON-NLS-1$
Vector<Byte> vctr = new Vector<Byte>();
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
addIntToVector(vctr, 1);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
return rpckt;
}
private ReplyPacket arrayReference(CommandPacket cpckt) throws Exception{
if (cpckt.getCommand() == 1){
byte [] inData = cpckt.getByteData();
long arrayObject = createLongFromBytes(inData, 0, 8);
logr.log(JDILogger.LEVEL_VERYVERBOSE, "ArrayReference.Length("+arrayObject+")"); //$NON-NLS-1$ //$NON-NLS-2$
JavaObject jObject = getObject(arrayObject);
if (jObject != null){
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
Vector<Byte> vctr = new Vector<Byte>();
addIntToVector(vctr, jObject.getArraySize());
logr.log(JDILogger.LEVEL_VERBOSE, " " + arrayObject + " Has length " + jObject.getArraySize()); //$NON-NLS-1$ //$NON-NLS-2$
//addIntToVector(vctr, 0);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
return rpckt;
}else if (cpckt.getCommand() == 2){
byte [] inData = cpckt.getByteData();
long arrayObject = createLongFromBytes(inData, 0, 8);
int firstIndex = createIntFromBytes(inData, 8, 4);
int length = createIntFromBytes(inData, 12, 4);
logr.log(JDILogger.LEVEL_VERYVERBOSE, "ArrayReference.GetValues("+arrayObject+","+firstIndex+","+length+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
JavaObject jObject = getObject(arrayObject);
if (jObject != null){
if (!jObject.isArray()){
logr.logError(JDILogger.LEVEL_VERYVERBOSE, " Not actually an array"); //$NON-NLS-1$
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
return rpckt;
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, " array type: " + jObject.getJavaClass().getName()); //$NON-NLS-1$
if (jObject.getJavaClass().getName().equals("[I")){ //$NON-NLS-1$
int []jObjs = new int[length];
jObject.arraycopy(firstIndex, jObjs, 0, length);
if (jObjs != null){
Vector<Byte> vctr = new Vector<Byte>();
logr.log(JDILogger.LEVEL_VERYVERBOSE, " got " + jObjs.length + " objects"); //$NON-NLS-1$ //$NON-NLS-2$
vctr.add((byte)'I');
addIntToVector(vctr, jObjs.length);
for(int i = 0; i < jObjs.length; i++){
addIntToVector(vctr, jObjs[i]);
logr.log(JDILogger.LEVEL_VERYVERBOSE, " " + jObjs[i]); //$NON-NLS-1$
}
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}
}else if (jObject.getJavaClass().getName().equals("[F")){ //$NON-NLS-1$
float []jObjs = new float[length];
jObject.arraycopy(firstIndex, jObjs, 0, length);
if (jObjs != null){
Vector<Byte> vctr = new Vector<Byte>();
logr.log(JDILogger.LEVEL_VERYVERBOSE, " got " + jObjs.length + " objects"); //$NON-NLS-1$ //$NON-NLS-2$
vctr.add((byte)'F');
addIntToVector(vctr, jObjs.length);
for(int i = 0; i < jObjs.length; i++){
addIntToVector(vctr, Float.floatToIntBits(jObjs[i]));
}
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}
}else if (jObject.getJavaClass().getName().equals("[S")){ //$NON-NLS-1$
short []jObjs = new short[length];
jObject.arraycopy(firstIndex, jObjs, 0, length);
if (jObjs != null){
Vector<Byte> vctr = new Vector<Byte>();
logr.log(JDILogger.LEVEL_VERYVERBOSE, " got " + jObjs.length + " objects"); //$NON-NLS-1$ //$NON-NLS-2$
vctr.add((byte)'S');
addIntToVector(vctr, jObjs.length);
for(int i = 0; i < jObjs.length; i++){
vctr.add((byte)((jObjs[i] >> 8) & 0xFF));
vctr.add((byte)(jObjs[i] & 0xFF));
}
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}
}else if (jObject.getJavaClass().getName().equals("[J")){ //$NON-NLS-1$
long []jObjs = new long[length];
jObject.arraycopy(firstIndex, jObjs, 0, length);
if (jObjs != null){
Vector<Byte> vctr = new Vector<Byte>();
logr.log(JDILogger.LEVEL_VERYVERBOSE, " got " + jObjs.length + " objects"); //$NON-NLS-1$ //$NON-NLS-2$
vctr.add((byte)'J');
addIntToVector(vctr, jObjs.length);
for(int i = 0; i < jObjs.length; i++){
addLongToVector(vctr, jObjs[i]);
}
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}
}else if (jObject.getJavaClass().getName().equals("[B")){ //$NON-NLS-1$
byte []jObjs = new byte[length];
jObject.arraycopy(firstIndex, jObjs, 0, length);
Vector<Byte> vctr = new Vector<Byte>();
logr.log(JDILogger.LEVEL_VERYVERBOSE, " got " + jObjs.length + " objects"); //$NON-NLS-1$ //$NON-NLS-2$
vctr.add((byte)'B');
addIntToVector(vctr, jObjs.length);
for(int i = 0; i < jObjs.length; i++){
vctr.add(jObjs[i]);
}
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}else if (jObject.getJavaClass().getName().equals("[Z")){ //$NON-NLS-1$
byte []jObjs = new byte[length];
jObject.arraycopy(firstIndex, jObjs, 0, length);
Vector<Byte> vctr = new Vector<Byte>();
logr.log(JDILogger.LEVEL_VERYVERBOSE, " got " + jObjs.length + " objects"); //$NON-NLS-1$ //$NON-NLS-2$
vctr.add((byte)'Z');
addIntToVector(vctr, jObjs.length);
for(int i = 0; i < jObjs.length; i++){
vctr.add(jObjs[i]);
}
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}else if (jObject.getJavaClass().getName().equals("[D")){ //$NON-NLS-1$
double []jObjs = new double[length];
jObject.arraycopy(firstIndex, jObjs, 0, length);
Vector<Byte> vctr = new Vector<Byte>();
logr.log(JDILogger.LEVEL_VERYVERBOSE, " got " + jObjs.length + " objects"); //$NON-NLS-1$ //$NON-NLS-2$
vctr.add((byte)'D');
addIntToVector(vctr, jObjs.length);
for(int i = 0; i < jObjs.length; i++){
addLongToVector(vctr, Double.doubleToLongBits(jObjs[i]));
}
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}else if (jObject.getJavaClass().getName().equals("[C")){ //$NON-NLS-1$
char []jObjs = new char[length];
jObject.arraycopy(firstIndex, jObjs, 0, length);
Vector<Byte> vctr = new Vector<Byte>();
logr.log(JDILogger.LEVEL_VERYVERBOSE, " got " + jObjs.length + " objects"); //$NON-NLS-1$ //$NON-NLS-2$
vctr.add((byte)'C');
addIntToVector(vctr, jObjs.length);
for(int i = 0; i < jObjs.length; i++){
vctr.add((byte)((jObjs[i] >> 8) & 0xFF));
vctr.add((byte)(jObjs[i] & 0xFF));
}
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
rpckt.setData(vectorToByte(vctr));
return rpckt;
} else{
JavaObject []jObjs = new JavaObject[length];
jObject.arraycopy(firstIndex, jObjs, 0, length);
logr.log(JDILogger.LEVEL_VERYVERBOSE, " got " + jObjs.length + "objects"); //$NON-NLS-1$ //$NON-NLS-2$
Vector<Byte> vctr = new Vector<Byte>();
vctr.add((byte)TAG_ARRAY);
addIntToVector(vctr, jObjs.length);
byte arrayTagType = (byte)TAG_OBJECT;
String arrayName = jObject.getJavaClass().getName();
if (arrayName.equals("[Ljava/lang/String;")){
arrayTagType = (byte)TAG_STRING;
}else if ( arrayName.charAt(1) == '['){
arrayTagType = (byte)TAG_ARRAY;
}
for(int i = 0; i < jObjs.length; i++){
// Also check if it is an array of interfaces
if (jObjs[i] != null){
vctr.add(arrayTagType);
addLongToVector(vctr, jObjs[i].getID().getAddress());
logr.log(JDILogger.LEVEL_VERYVERBOSE, " jObjs["+i+"] address " + jObjs[i].getID().getAddress()); //$NON-NLS-1$ //$NON-NLS-2$
logr.log(JDILogger.LEVEL_VERYVERBOSE, " jObjs["+i+"] type " + jObjs[i].getJavaClass().getName()); //$NON-NLS-1$ //$NON-NLS-2$
if (!objectMap.containsKey(jObjs[i].getID().getAddress())){
objectMap.put(jObjs[i].getID().getAddress(), jObjs[i]);
}
if (!classes.containsKey(jObjs[i].getJavaClass().getID().getAddress())){
logr.log(JDILogger.LEVEL_VERYVERBOSE, " Class is not of registered type"); //$NON-NLS-1$
}
}else{
vctr.add((byte)TAG_OBJECT);
addLongToVector(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_INVALID_OBJECT);
return rpckt;
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
return rpckt;
}
private ReplyPacket eventRequest(CommandPacket cpckt) throws Exception{
if (cpckt.getCommand() == 1){
byte [] inData = cpckt.getByteData();
int eventKind = inData[0];
int suspendPolicy = inData[1];
int modifiers = createIntFromBytes(inData, 2, 4);
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Set("+eventKind+","+suspendPolicy+","+modifiers+", ...)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
for (int i = 0; i < modifiers; i++){
int modKind = inData[6 + (6*i)];
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Set(Modkind"+modKind+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
if (modKind == 5){
String classPattern = getStringFromBytes(inData, 6 + (6*i) + 1);
logr.log(JDILogger.LEVEL_VERYVERBOSE, "ClassMatch(\"" + classPattern + "\")"); //$NON-NLS-1$ //$NON-NLS-2$
}else{
logr.log(JDILogger.LEVEL_VERYVERBOSE, "modKind: " + modKind); //$NON-NLS-1$
}
}
ReplyPacket rpckt;
if (eventKind == 8){
rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_CLASS);
return rpckt;
}else{
}
rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
Vector<Byte> vctr = new Vector<Byte>();
addIntToVector(vctr, LAST_ID++);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}else if (cpckt.getCommand() == 2){
logr.log(JDILogger.LEVEL_VERBOSE, "Ignoring event request");
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
return rpckt;
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
return rpckt;
}
private ReplyPacket stackFrame(CommandPacket cpckt) throws Exception{
if (cpckt.getCommand() == 1){
byte []inData = cpckt.getByteData();
long threadID = createLongFromBytes(inData, 0, 8);
long frameID = createLongFromBytes(inData, 8, 8);
int slots = createIntFromBytes(inData, 16, 4);
logr.log(JDILogger.LEVEL_VERBOSE, "StackFrame.GetValues(" + threadID + "," + frameID + "," + slots + ",...)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
Vector<Byte> vctr = new Vector<Byte>();
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
addIntToVector(vctr, slots);
Iterator asIt = image.getAddressSpaces( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) )
{
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
Iterator thds = javaRT.getThreads().iterator();
while(thds.hasNext()){
Object tmpobj = thds.next();
if (tmpobj instanceof CorruptData){
//ignore this thread
}else{
JavaThread thd = (JavaThread) tmpobj;
if (thd.getObject().getID().getAddress() == threadID){
Iterator frames = thd.getStackFrames().iterator();
while(frames.hasNext()){
JavaStackFrame jFrame = (JavaStackFrame)frames.next();
if (jFrame.getBasePointer().getAddress() == frameID){
// vctr.add((byte)'L');
// addLongToVector(vctr,jFrame.getLocation().getMethod().getDeclaringClass().getID().getAddress());
// logr.log(JDILogger.LEVEL_VERBOSE, " " + jFrame.getLocation().getMethod().getDeclaringClass().getID().getAddress()); //$NON-NLS-1$
// Get slot number and type of each requested variable.
GETVALUESLOTS: for (int i=0; i < slots; i++) {
int slot = createIntFromBytes(inData, 20+5*i, 4);
byte type = inData[20+5*i+4];
Object value = jFrame.getVariable(slot);
logr.log(JDILogger.LEVEL_VERYVERBOSE, "OBJECT("+value+")");
switch(type) {
case TAG_ARRAY:
long arrayAddress = 0L;
vctr.add((byte)TAG_ARRAY);
if (value instanceof JavaObject) {
JavaObject obj = (JavaObject) value;
if (obj.isArray()) {
arrayAddress = obj.getID().getAddress();
}
}
logr.log(JDILogger.LEVEL_VERBOSE, " " +jFrame.getLocation() + " Array in slot=" + slot + " value="+arrayAddress);
addLongToVector(vctr, arrayAddress );
break;
case TAG_BYTE:
byte byteVal = -1;
vctr.add((byte)TAG_BYTE);
if (value instanceof Number) {
Number num = (Number) value;
byteVal = num.byteValue();
}
logr.log(JDILogger.LEVEL_VERBOSE, " " +jFrame.getLocation() + " byte in slot=" + slot + " value="+byteVal);
vctr.add(byteVal);
break;
case TAG_CHAR:
char charVal = (char) -1;
vctr.add((byte)TAG_CHAR);
if (value instanceof Character) {
charVal = (Character) value;
}
logr.log(JDILogger.LEVEL_VERBOSE, " " +jFrame.getLocation() + " byte in slot=" + slot + " value="+charVal);
addCharToVector(vctr, charVal);
break;
case TAG_OBJECT:
long objectAddress = 0L;
byte typeTag = (byte)TAG_OBJECT;
if (value instanceof JavaObject) {
JavaObject obj = (JavaObject) value;
objectAddress = obj.getID().getAddress();
if (obj != null){
if (obj.getJavaClass().getName().equals("java/lang/String")){
typeTag = (byte)TAG_STRING;
}
}
}
vctr.add(typeTag);
logr.log(JDILogger.LEVEL_VERBOSE, " " +jFrame.getLocation() + " Object in slot=" + slot + " value="+objectAddress);
addLongToVector(vctr, objectAddress );
break;
case TAG_FLOAT:
float floatVal = -1;
vctr.add((byte)TAG_FLOAT);
if (value instanceof Number) {
Number num = (Number) value;
floatVal = num.floatValue();
}
logr.log(JDILogger.LEVEL_VERBOSE, " " +jFrame.getLocation() + " float in slot=" + slot + " value="+floatVal);
addIntToVector(vctr, Float.floatToIntBits(floatVal));
break;
case TAG_DOUBLE:
double doubleVal = -1;
vctr.add((byte)TAG_DOUBLE);
if (value instanceof Number) {
Number num = (Number) value;
doubleVal = num.doubleValue();
}
logr.log(JDILogger.LEVEL_VERBOSE, " " +jFrame.getLocation() + " double in slot=" + slot + " value="+doubleVal);
addLongToVector(vctr, Double.doubleToLongBits(doubleVal));
break;
case TAG_INT:
int intVal = -1;
vctr.add((byte)TAG_INT);
if (value instanceof Number) {
Number num = (Number) value;
intVal = num.intValue();
}
logr.log(JDILogger.LEVEL_VERBOSE, " " +jFrame.getLocation() + " int in slot=" + slot + " value="+intVal);
addIntToVector(vctr, intVal);
break;
case TAG_LONG:
long longVal = -1;
vctr.add((byte)TAG_LONG);
if (value instanceof Number) {
Number num = (Number) value;
longVal = num.longValue();
}
logr.log(JDILogger.LEVEL_VERBOSE, " " +jFrame.getLocation() + " long in slot=" + slot + " value="+longVal);
addLongToVector(vctr, longVal);
break;
case TAG_SHORT:
short shortVal = -1;
vctr.add((byte)TAG_SHORT);
if (value instanceof Number) {
Number num = (Number) value;
shortVal = num.shortValue();
}
logr.log(JDILogger.LEVEL_VERBOSE, " " +jFrame.getLocation() + " short in slot=" + slot + " value="+shortVal);
addShortToVector(vctr, shortVal);
break;
case TAG_BOOLEAN:
boolean booleanVal = false;
vctr.add((byte)TAG_BOOLEAN);
if (value instanceof Boolean) {
booleanVal = ((Boolean) value);
}
logr.log(JDILogger.LEVEL_VERBOSE, " " +jFrame.getLocation() + " boolean in slot=" + slot + " value="+booleanVal);
vctr.add(booleanVal ? (byte) 1 : (byte) 0);
break;
case TAG_STRING:
String stringVal= "";
vctr.add((byte)TAG_STRING);
if (value instanceof JavaObject) {
stringVal = javaObjectToString( (JavaObject) value);
}
logr.log(JDILogger.LEVEL_VERBOSE, " " +jFrame.getLocation() + " string in slot=" + slot + " value=\""+stringVal+"\"");
addStringToVector(vctr, stringVal);
break;
default:
logr.log(JDILogger.LEVEL_VERBOSE, " " +jFrame.getLocation() + " unable to handle type "+type+" in "+jFrame.getLocation());
rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
vctr = new Vector<Byte>();
break GETVALUESLOTS;
}
}
}
}
}
}
}
}
}
}
rpckt.setData(vectorToByte(vctr));
return rpckt;
}else if (cpckt.getCommand() == 3){
byte []inData = cpckt.getByteData();
long threadID = createLongFromBytes(inData, 0, 8);
long frameID = createLongFromBytes(inData, 8, 8);
//TODO - Get this to work
logr.log(JDILogger.LEVEL_VERBOSE, "ThisObject(" + threadID + "," + frameID + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Iterator asIt = image.getAddressSpaces( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) )
{
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
Iterator thds = javaRT.getThreads().iterator();
while(thds.hasNext()){
Object tmpobj = thds.next();
if (tmpobj instanceof CorruptData){
//ignore this thread
}else{
JavaThread thd = (JavaThread) tmpobj;
if (thd.getObject().getID().getAddress() == threadID){
Iterator frames = thd.getStackFrames().iterator();
while(frames.hasNext()){
JavaStackFrame jFrame = (JavaStackFrame)frames.next();
if (jFrame.getBasePointer().getAddress() == frameID){
Vector<Byte> vctr = new Vector<Byte>();
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
if ((jFrame.getLocation().getMethod().getModifiers() & Modifier.STATIC) !=0) {
addLongToVector(vctr, 0); // Return null as static method.
} else {
Object value = jFrame.getVariable(0);
long objectAddress = 0;
if (value != null && value instanceof JavaObject) {
JavaObject obj = (JavaObject) value;
objectAddress = obj.getID().getAddress();
}
vctr.add((byte)TAG_OBJECT);
logr.log(JDILogger.LEVEL_VERBOSE, " " +jFrame.getLocation() + " return this object value="+objectAddress+" "+value);
addLongToVector(vctr, objectAddress );
}
rpckt.setData(vectorToByte(vctr));
return rpckt;
}
}
}
}
}
}
}
}
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
return rpckt;
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
return rpckt;
}
private byte getRefTypeTag(JavaClass jcl){
byte refTypeTag = 1;
try {
if (jcl.isArray()){
refTypeTag = 3;
}else if(isInterface(jcl.getID().getAddress())){
refTypeTag = 2;
}
} catch (CorruptDataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return refTypeTag;
}
private ReplyPacket classLoaderRef(CommandPacket cpckt) throws Exception{
if (cpckt.getCommand() == 1){
byte []inData = cpckt.getByteData();
long classLoaderID = createLongFromBytes(inData, 0, 8);
logr.log(JDILogger.LEVEL_VERBOSE, "VisibleClasses(" + classLoaderID + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
int count = 0;
Vector<Byte> vctr = new Vector<Byte>();
Vector<JavaClassLoader> jcls = new Vector<JavaClassLoader>();
for (JavaClass jc: classes.values()){
JavaObject obj;
if ((obj = jc.getClassLoader().getObject()) != null){
if (obj.getID().getAddress() == classLoaderID){
jcls.add(jc.getClassLoader());
jc = jc.getClassLoader().getObject().getJavaClass();
while (jc.getClassLoader()!= null){
jcls.add(jc.getClassLoader());
jc = jc.getClassLoader().getObject().getJavaClass();
}
break;
}
}
}
for (JavaClass jc: classes.values()){
for (JavaClassLoader jcl : jcls){
if (jc.getClassLoader() == jcl){
vctr.add(getRefTypeTag(jc));
addLongToVector(vctr, jc.getID().getAddress());
count++;
}
}
}
addIntToVectorFront(vctr, count);
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
rpckt.setData(vectorToByte(vctr));
return rpckt;
}
return null;
}
private ReplyPacket threadGroupReference(CommandPacket cpckt) throws Exception{
if (cpckt.getCommand() == 1){
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
Vector<Byte> vctr = new Vector<Byte>();
addStringToVector(vctr, "All threads");
rpckt.setData(vectorToByte(vctr));
return rpckt;
} else if (cpckt.getCommand() == 2){
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
Vector<Byte> vctr = new Vector<Byte>();
addLongToVector(vctr, 0);
rpckt.setData(vectorToByte(vctr));
return rpckt;
} else if (cpckt.getCommand() == 3){
logr.log(JDILogger.LEVEL_VERBOSE, "Returning all threads as single group"); //$NON-NLS-1$
Iterator asIt = image.getAddressSpaces( ).iterator();
while ( asIt.hasNext( ) )
{
ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
Iterator prIt = as.getProcesses( ).iterator();
while ( prIt.hasNext( ) )
{
ImageProcess process = (ImageProcess) prIt.next( );
Iterator runTimesIt = process.getRuntimes( ).iterator();
while ( runTimesIt.hasNext( ) )
{
JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
Iterator thds = javaRT.getThreads().iterator();
Vector<Byte> vctr = new Vector<Byte>();
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 + " id is "+thd.getObject().getID()) ; //$NON-NLS-1$ //$NON-NLS-2$
addLongToVector(vctr, hash);
}
}
addIntToVectorFront(vctr, count);
addIntToVector(vctr, 0);
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
byte []barray2 = vectorToByte(vctr);
rpckt.setData(barray2);
return rpckt;
}
}
}
}
logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
return rpckt;
}
public boolean isOk(){
return (errorCode == 0);
}
public void stop(){
shutDownKato();
}
private void shutDownKato(){
vctrs.clear();
intToMethod.clear();
classes.clear();
intToMethod.clear();
methodToInt.clear();
fieldList.clear();
objectMap.clear();
image = null;
vctrs = null;
classes = null;
intToMethod = null;
methodToInt = null;
fieldList = null;
objectMap = null;
}
}