From kato-commits-return-633-apmail-incubator-kato-commits-archive=incubator.apache.org@incubator.apache.org Fri Sep 18 16:11:08 2009 Return-Path: Delivered-To: apmail-incubator-kato-commits-archive@minotaur.apache.org Received: (qmail 39841 invoked from network); 18 Sep 2009 16:11:08 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 18 Sep 2009 16:11:08 -0000 Received: (qmail 89990 invoked by uid 500); 18 Sep 2009 16:11:08 -0000 Delivered-To: apmail-incubator-kato-commits-archive@incubator.apache.org Received: (qmail 89974 invoked by uid 500); 18 Sep 2009 16:11:08 -0000 Mailing-List: contact kato-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: kato-dev@incubator.apache.org Delivered-To: mailing list kato-commits@incubator.apache.org Received: (qmail 89964 invoked by uid 99); 18 Sep 2009 16:11:08 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 18 Sep 2009 16:11:08 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 18 Sep 2009 16:10:57 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 9CBE02388906; Fri, 18 Sep 2009 16:10:35 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r816693 [2/2] - in /incubator/kato/trunk/org.apache.kato/kato.cjvmti/src/main/java/org/apache/kato/jvmti: javaruntime/ javaruntime/model/ reader/ Date: Fri, 18 Sep 2009 16:10:35 -0000 To: kato-commits@incubator.apache.org From: monteith@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090918161035.9CBE02388906@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: incubator/kato/trunk/org.apache.kato/kato.cjvmti/src/main/java/org/apache/kato/jvmti/reader/CJVMTIBinReader.java URL: http://svn.apache.org/viewvc/incubator/kato/trunk/org.apache.kato/kato.cjvmti/src/main/java/org/apache/kato/jvmti/reader/CJVMTIBinReader.java?rev=816693&r1=816692&r2=816693&view=diff ============================================================================== --- incubator/kato/trunk/org.apache.kato/kato.cjvmti/src/main/java/org/apache/kato/jvmti/reader/CJVMTIBinReader.java (original) +++ incubator/kato/trunk/org.apache.kato/kato.cjvmti/src/main/java/org/apache/kato/jvmti/reader/CJVMTIBinReader.java Fri Sep 18 16:10:34 2009 @@ -46,8 +46,11 @@ import org.apache.kato.jvmti.javaruntime.model.JThread; import org.apache.kato.jvmti.javaruntime.model.Model; - - +/** + * + * CJVMTIBinReader - Reads cjvmti dump files + * + */ public class CJVMTIBinReader { private static final byte CJVMTI_BYTE = 0x1c; @@ -90,14 +93,13 @@ private static final byte CJVMTI_CLASS_INTERFACES = 0x24; private long selfGeneratedIDs; private int selfGeneratedMonitorIDs = 1; - FileImageInputStream in = null; FileImageInputStream variablesIn = null; Model model = new Model(); static Logger log = CLogger.logr; JClassLoader readerJCL;// Class loader for reader generated classes JClassLoader bootJCL;// Class loader for boot class loader (return nulls in - + // jvmti JClass intArray;// "[int" // @@ -117,107 +119,93 @@ JObject nullObject; HashMap objectArrayClasses; + public static void simpler(Model m, Model m2){ + System.out.println(""); + } @SuppressWarnings("unchecked") public static void main(String[] args) { - - File f = new File("c:\\cjvmti.cdmp"); + + File f = new File("c:\\cjvmtiV0.cdmp"); + File f2 = new File("c:\\cjvmtiVDu.cdmp"); log.setLevel(Level.ALL); ConsoleHandler handle = new ConsoleHandler(); - handle.setLevel(Level.FINER); + handle.setLevel(Level.ALL); log.addHandler(handle); - - log.log(Level.FINEST,f.toString()); + + log.log(Level.FINEST, f.toString()); CJVMTIBinReader cjvm = null; + CJVMTIBinReader cjvmEx = null; try { cjvm = new CJVMTIBinReader(f); + cjvmEx = new CJVMTIBinReader(f2); } catch (IOException e) { e.printStackTrace(); System.exit(0); } - log.log(Level.FINER,""); - log.log(Level.FINER,""); - log.log(Level.FINER,""); + simpler(cjvm.model, cjvmEx.model); + log.log(Level.FINER, ""); + log.log(Level.FINER, ""); + log.log(Level.FINER, ""); + cjvmEx.toString(); List jthreads = cjvm.getModel().getThreads(); for (JavaThread t : jthreads) { try { - log.log(Level.FINEST,t.getName()); + log.log(Level.FINEST, t.getName()); for (JavaStackFrame jsf : t.getStackFrames()) { for (JavaVariable jv : jsf.getVariables()) { try { - log.log(Level.FINEST,"" + jv.getName() + " " + log.log(Level.FINEST, "" + jv.getName() + " " + jv.getSignature() + " "); } catch (DataUnavailable e) { // TODO Auto-generated catch block e.printStackTrace(); } - log.log(Level.FINEST,"" + jv.getValue()); + log.log(Level.FINEST, "" + jv.getValue()); } } } catch (CorruptDataException e) { - // TODO Auto-generated catch block e.printStackTrace(); } } - - - -// try { -// JavaClass jclC = cjvm.getModel().getObjectAtAddress(376679) -// .getJavaClass(); -// JavaObject obj = cjvm.getModel().getObjectAtAddress(376679); -// log.log(Level.FINEST," num Fields " + ((JObject) obj).getNumFields()); -// log.log(Level.FINEST," " + jclC.getID().getAddress()); -// while (jclC != null) { -// for (JavaField field : jclC.getDeclaredFields()) { -// if (field.getSignature().equals("Ljava/lang/String;")) { -// log.log(Level.FINEST,"Found string"); -// log.log(Level.FINEST,field.getSignature() + " field " -// + field.getName() + " " + jclC.getName()); -// -// try { -// log.log(Level.FINEST,"HEre" + field.getString(obj)); -// } catch (MemoryAccessException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } -// } -// } -// jclC = jclC.getSuperclass(); -// } -// } catch (CorruptDataException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } -// log.log(Level.FINEST," "+cjvm.getModel().getObjectAtAddress(380215)); - log.log(Level.INFO,"Finished test read"); + + log.log(Level.INFO, "Finished test read"); } + /** + * Attempts to read in a cjvmti dump file + * @param base Target file + * @throws IOException + */ public CJVMTIBinReader(File base) throws IOException { - RandomAccessFile raf = new RandomAccessFile(base, "r"); - in = new FileImageInputStream(raf); - RandomAccessFile dumpF = raf; + boolean bigEndian = true; + + //log.setLevel(Level.ALL); + ConsoleHandler handle = new ConsoleHandler(); + //handle.setLevel(Level.ALL); + //log.addHandler(handle); + + //log.log(Level.FINEST, base.toString()); // Currently split file setout, open variable file - RandomAccessFile raf2 = new RandomAccessFile(new File(base.getParent() - + "\\cjvmtiV.cdmp"), "r"); + RandomAccessFile raf2 = new RandomAccessFile(base, "r"); variablesIn = new FileImageInputStream(raf2); - selfGeneratedIDs = variablesIn.length() + 1; - if (dumpF.readInt() == 1) { - in.setByteOrder(ByteOrder.BIG_ENDIAN); + + selfGeneratedIDs = variablesIn.length() + 1; // Ensure classes generated by the reader do not collide with dump file class references + variablesIn.readLong(); + if (variablesIn.readInt() == 1) { variablesIn.setByteOrder(ByteOrder.BIG_ENDIAN); } else { - in.setByteOrder(ByteOrder.LITTLE_ENDIAN); variablesIn.setByteOrder(ByteOrder.LITTLE_ENDIAN); } - variablesIn.read(); - dumpF.seek(0); + variablesIn.seek(0); + variablesIn.readLong(); // check Endian setting - if (in.readInt() != 1) { + if (variablesIn.readInt() != 1) { System.err .println("Incorrect format for reader/failed to set endian"); throw new IOException(); @@ -226,49 +214,62 @@ StringBuilder sb = new StringBuilder(); for (int i = 0; i < 12; i++) { - sb.append((char) in.readByte()); + sb.append((char) variablesIn.readByte()); } if (!sb.toString().equals("CJVMTI V0.01")) { - System.err.println("Incorrect format for reader"); + System.err.println("Incorrect format for reader _" + sb.toString() + + "_"); throw new IOException(); } - log.log(Level.INFO,"CJVMTI Format V0.01"); - log.log(Level.INFO,"Starting reading in.."); - - Long time = in.readLong(); + log.log(Level.INFO, "CJVMTI Format V0.01"); + log.log(Level.INFO, "Starting reading in.."); + Long time = variablesIn.readLong(); Date creationDate = new Date((time * 1000)); - log.log(Level.INFO,"Date of creation: " + creationDate.toString()); + log.log(Level.INFO, "Date of creation: " + creationDate.toString()); JMonitor.model = model; generateClassLoaderForReader(); generatePrimitiveArrayClasses(); - // check id - - while (true) { + + byte recordGroup = 0; try { - recordGroup = (byte) in.readUnsignedByte(); - log.log(Level.FINEST,"RG: " + recordGroup); + recordGroup = (byte) variablesIn.readUnsignedByte(); + log.log(Level.FINEST, "RG: " + recordGroup); } catch (EOFException ee) { - log.log(Level.FINEST,"Finished"); - break; + log.log(Level.FINEST, "Finished"); } + + switch (recordGroup) { case CJVMTI_THREAD: - nreadThread(in.getStreamPosition() - 1); + int numThreads = variablesIn.readInt(); + long threadRefs[] = new long[numThreads]; + for (int i = 0; i < numThreads; i++){ + threadRefs[i] = variablesIn.readLong(); + } + for (int i = 0; i < numThreads; i++) { + log.finest("Reading thread at "+Long.toHexString(threadRefs[i])); + nreadThread(threadRefs[i]); + } break; default: error("record group " + recordGroup + " is not understood"); } - } - log.log(Level.INFO,"CJVMTI bin reader complete" ); + + log.log(Level.INFO, "CJVMTI bin reader complete"); } - private JLocalVariableTableEntry nlocalVarTable(JClass c) + /** + * Local variable table information + * @return + * @throws IOException + */ + private JLocalVariableTableEntry nlocalVarTable() throws IOException { // log.log(Level.FINEST,"Get local var table"); String name = readCString(variablesIn); @@ -288,6 +289,11 @@ return jlvt; } + /** + * Method information + * @param c Defining class + * @throws IOException + */ private void nmethodDetails(JClass c) throws IOException { if (variablesIn.readByte() != CJVMTI_METHOD) throw new IOException(); @@ -297,17 +303,23 @@ String mGenSig = readCString(variablesIn); int modifiers = variablesIn.readInt(); int count = variablesIn.readInt(); + + JMethod jm = model.getMethod(methodID); jm.name = mName; jm.signature = mSig; if (mGenSig.equals(" ")) { - jm.genericsignature = null; + jm.genericsignature = null; // Not currently keeping it null, left as reminder } jm.genericsignature = mGenSig; jm.mods = modifiers; + for (int i = 0; i < count; i++) { - jm.addLocalVariableTableEntry(nlocalVarTable(c)); + JLocalVariableTableEntry jlte = nlocalVarTable(); + jm.addLocalVariableTableEntry(jlte); } + + // Line number table int lntLength = variablesIn.readInt(); for (int i = 0; i < lntLength; i++) { int lNum = variablesIn.readInt(); @@ -317,6 +329,12 @@ c.addMethod(jm); } + /** + * Static field details + * @param c Defining class + * @return Number of static fields + * @throws IOException + */ private int nstaticFieldDetails(JClass c) throws IOException { int fieldCount = variablesIn.readInt(); for (int i = 0; i < fieldCount; i++) { @@ -331,11 +349,16 @@ fl.signature = sig; fl.staticField = true; fl.modifiers = modifiers; - fl.index = i; // used to fill in fields + fl.index = i; // Used to ensure references are filled in the order when filling in static values } return fieldCount; } + /** + * Instance field details + * @param c Defining class + * @throws IOException + */ private void instanceFieldDetails(JClass c) throws IOException { int fieldCount = variablesIn.readInt(); for (int i = 0; i < fieldCount; i++) { @@ -351,10 +374,15 @@ fl.staticField = false; fl.modifiers = modifiers; fl.index = i; // used to fill in fields - // log.log(Level.FINEST,"Field " + fl.index); } } + /** + * Read class at defined position + * @param ref Position in file + * @return + * @throws IOException + */ private JClass nreadClass(long ref) throws IOException { variablesIn.seek(ref); if (ref == 0) { @@ -362,33 +390,43 @@ if (variablesIn.readByte() == CJVMTI_CLASS) { return nreadClass(); } else { - log.log(Level.FINEST,"IO EX" + Long.toHexString(ref)); + log.log(Level.FINEST, "IO EX" + Long.toHexString(ref)); throw new IOException(); } } + /** + * Read class at current position + * @return + * @throws IOException + */ private JClass nreadClass() throws IOException { long id = variablesIn.getStreamPosition(); - id--; + id--; // Class id/ImagePointer + JClass c = model.getClass(id); + + // Prevent reference loops (check if this class is partly filled in) if (c.classSig != null) return c; + int modifiers = variablesIn.readInt(); c.modifiers = (short) modifiers; - log.log(Level.FINEST,"mods " + modifiers + " " + c.modifiers); + log.log(Level.FINEST, "mods " + modifiers + " " + c.modifiers); String name = readCString(variablesIn); String sourceFile = readCString(variablesIn); String genSig = readCString(variablesIn); // TODO move this to C implementation if (sourceFile.equals("NoSource")) { - sourceFile = null; + if (!(name.indexOf("[")>-1)&&name.indexOf("L")>-1){ + sourceFile = name.substring(name.lastIndexOf("/")+1, name.indexOf(";")); // Small attempt to extend number of sourcefiles reported to Eclipse + } } c.classSig = name; c.classid = id; c.sourceFile = sourceFile; - long currentFileLoc = variablesIn.getStreamPosition(); - variablesIn.seek(currentFileLoc); + if (variablesIn.readByte() == CJVMTI_METHOD) { int num = variablesIn.readInt(); for (int i = 0; i < num; i++) { @@ -444,19 +482,19 @@ } else { throw new IOException(); } + c.superClassID = supC; - c.locIn = 1; if (supC != CJVMTI_NULL_OBJECT) { c.superclass = nreadClass(supC); } - c.locIn = 2; - // Use index to fill into \the correct slot + + // Read static field references for (JField fl : (List) c.getDeclaredFields()) { if (fl.staticField) { fl.staticValue = nreadReference(refs[fl.index]); } } - log.log(Level.FINEST,"num interf: " + interfaceClasses.length + " " + log.log(Level.FINEST, "num interf: " + interfaceClasses.length + " " + c.classSig); // Follow interface references for (long interfaceRef : interfaceClasses) { @@ -468,7 +506,7 @@ if (classLoaderRef == 0) { bootJCL.addClass(c); c.classloader = bootJCL; - //c.classloader = null; + // c.classloader = null; } else { JClassLoader jcl = model.getLoader(classLoaderRef); jcl.addClass(c); @@ -478,7 +516,7 @@ } c.classloader = jcl; try { - log.log(Level.FINEST,"Class loader : " + log.log(Level.FINEST, "Class loader : " + c.getClassLoader().getObject().getJavaClass() .getName() + " for " + c.getName()); } catch (CorruptDataException e) { @@ -486,16 +524,16 @@ e.printStackTrace(); } } - c.locIn = 3; - - if (c.classloader == null) { - //log.log(Level.FINEST,"No valid class loader"); - //System.exit(0); - } return c; } + /** + * Conveniance class for loading objects + * @param position Position in file + * @return Populated JObject or null + * @throws IOException + */ private JObject nreadObject(long position) throws IOException { variablesIn.seek(position); if (position == CJVMTI_NULL_OBJECT) { @@ -508,6 +546,11 @@ } } + /** + * Reads an object at the current file position + * @return Populated java object + * @throws IOException + */ private JObject nreadObject() throws IOException { long objectID = variablesIn.getStreamPosition() - 1; long classRef = variablesIn.readLong(); @@ -515,14 +558,15 @@ long offset = variablesIn.getStreamPosition(); // log.log(Level.FINEST,"objectID " + Long.toHexString(objectID)); JClass c = nreadClass(classRef); - log.log(Level.FINEST,"Obj id " + Long.toHexString(objectID)); + log.log(Level.FINEST, "Obj id " + Long.toHexString(objectID)); JObject obj = model.getObject(classRef, objectID); + if (obj.visited) return obj; // Prevent reference loop - obj.visited = true; + + // Calculate how many instance fields the reader can see on the class hierarchy int instanceFieldCount = 0; - JClass superClass = c; while (superClass != null) { for (JField jf : (List) superClass.getDeclaredFields()) { @@ -531,12 +575,15 @@ } superClass = model.getClass(superClass.superClassID); } + + // Check they match the dump files recoard if (numInstanceFields != instanceFieldCount) { - log.log(Level.FINEST,"Non-matching " + numInstanceFields + " found " - + instanceFieldCount); + log.log(Level.FINEST, "Non-matching " + numInstanceFields + + " found " + instanceFieldCount); System.exit(0); } + // Now read in all the references long instanceRefs[] = new long[instanceFieldCount]; variablesIn.seek(offset); int countUp = 0; @@ -545,8 +592,10 @@ countUp++; } offset = variablesIn.getStreamPosition(); + + + // Follow the references grabbing the correct jfield for the hierarchy of classes int fieldCount = 0; - int fieldOffset; fieldOffset = 0; superClass = c; @@ -554,6 +603,10 @@ for (JField jf : (List) superClass.getDeclaredFields()) { if (!jf.staticField) { fieldCount++; + if (instanceRefs[fieldOffset +jf.index] == 0x9999999999999999L){ + log.fine("Error, unwritten reference"); + } + log.finest("Reading in "+fieldCount); obj .addValue(jf.getFieldID(), @@ -566,11 +619,17 @@ superClass = model.getClass(superClass.superClassID); } - log.log(Level.FINEST," " + fieldCount + " " + numInstanceFields + " " + log.log(Level.FINEST, " " + fieldCount + " " + numInstanceFields + " " + instanceFieldCount + " " + c.classSig); return obj; } + /** + * Takes a reference (and thus a file position) and returns a populated object + * @param position Position in file + * @return + * @throws IOException + */ private Object nreadReference(long position) throws IOException { if (position == CJVMTI_NULL_OBJECT) { return null; @@ -606,7 +665,7 @@ long classType = variablesIn.readLong(); length = variablesIn.readInt(); long currentReadPos = variablesIn.getStreamPosition(); - log.log(Level.FINEST,"pos " + classType); + log.log(Level.FINEST, "Object Array " + classType); JClass arrayClass = nreadClass(classType); variablesIn.seek(currentReadPos); JObject objA[] = new JObject[length]; @@ -617,7 +676,7 @@ objA[counter] = (JObject) null; continue; } - log.log(Level.FINEST,"Reading " + counter + " at " + log.log(Level.FINEST, "Reading " + counter + " at " + Long.toHexString(objReference)); currentReadPos = variablesIn.getStreamPosition(); objA[counter] = (JObject) nreadReference(objReference); @@ -725,68 +784,37 @@ System.exit(0); } } catch (Exception e) { - log.log(Level.FINEST,e.toString()); + + log.log(Level.FINEST, e.toString()); e.printStackTrace(); + log.finest("Tried to read at "+Long.toHexString(position)); System.exit(0); } return null; } + + /** + * This is used to simulate the java boot class loader + */ private void generateClassLoaderForReader() { - // generate system classloader - - - - selfGeneratedIDs++; - JClassLoader rootJCL = model.getLoader(selfGeneratedIDs); - JClass rootCLC = model.getClass(selfGeneratedIDs); - rootCLC.classSig = "Ljava/lang/SystemClassLoaderBASE;"; - JObject rootObj = model.getObject(selfGeneratedIDs, selfGeneratedIDs); - rootJCL.obj = rootObj; - selfGeneratedIDs++; - - + // generate system classloader + selfGeneratedIDs++; bootJCL = model.getLoader(selfGeneratedIDs); JClass bootCLC = model.getClass(selfGeneratedIDs); bootCLC.classSig = "Ljava/lang/CJVMTISystemClassLoader;"; JObject bootObj = model.getObject(selfGeneratedIDs, selfGeneratedIDs); bootJCL.obj = bootObj; - //rootJCL.addClass(bootCLC); + // rootJCL.addClass(bootCLC); bootCLC.classloader = null; readerJCL = bootJCL; } - - - - private JClass getArrayClass(JObject type) { - if (objectArrayClasses == null) { - objectArrayClasses = new HashMap(); - } - if (objectArrayClasses.get(type) != null) { - return objectArrayClasses.get(type); - } else { - selfGeneratedIDs++; - JClass c = model.getClass(selfGeneratedIDs); - try { - c.classSig = "[" + type.getJavaClass().getName(); - } catch (CorruptDataException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - c.classSig = "LUnknownObjectArray;"; - } - readerJCL.addClass(c); - objectArrayClasses.put(type, c); - return c; - } - } - - private void generateNullObject() { - selfGeneratedIDs++; - - } + /** + * Manually add the primitive array classes + */ private void generatePrimitiveArrayClasses() { // "[int" selfGeneratedIDs++; @@ -837,16 +865,12 @@ readerJCL.addClass(charArray); } - private String readName() throws IOException { - int nameLength = in.readInt(); - if (nameLength > 0) { - byte name[] = new byte[nameLength]; - in.readFully(name); - return new String(name); - } - return null; - } - + /** + * Read a C style null terminated string + * @param z Input stream pointing at the start of the string + * @return + * @throws IOException + */ private String readCString(FileImageInputStream z) throws IOException { StringBuilder sb = new StringBuilder(); char cur; @@ -856,152 +880,205 @@ return sb.toString(); } - public JLocalVariable nreadLocalVars() throws IOException { - JLocalVariable jlv = new JLocalVariable(); - String sig = readCString(in); - String name = readCString(in); - int length = in.readInt(); - int slot = in.readInt(); - long reference = in.readLong(); - nreadReference(reference); - jlv.slot = slot; - jlv.setValue(nreadReference(reference)); - return jlv; - } - - private void nreadFrames(JThread t) throws IOException { - long startPos; - int frameCount = in.readInt(); - if (frameCount == 0) - log.log(Level.FINEST,"No Frames"); - for (int i = 0; i < frameCount; i++) { - startPos = in.getStreamPosition(); - if (in.readByte() == CJVMTI_FRAME) { - log.log(Level.FINEST,"Reading frame" + i + " of " + frameCount); - long frameSize = in.readLong(); - byte jvmtiErr = in.readByte(); - if (jvmtiErr == CJVMTI_JVMTI_ERROR) { - log.log(Level.FINEST,"Data not available"); - in.seek(startPos + frameSize + 1); - continue; - } - long methodID = in.readLong(); - String methodName = readCString(in); - log.log(Level.FINEST,"Method name is: " + methodName); - long declaringClass = in.readLong(); - Object o = (JClass) nreadReference(declaringClass); // Get class - // info for - // this - // frame - JClass clazz = null; - if (!(clazz instanceof JClass)) { - clazz = (JClass) o; - } - byte depth = in.readByte(); + + + /** + * Read a stack frame + * @param pos Position of frame in file + * @param t Thread the frame is contained in + * @throws IOException + */ + private void nreadFrames(long pos, JThread t) throws IOException { + variablesIn.seek(pos); + byte val = variablesIn.readByte(); + if (val == CJVMTI_FRAME){ + log.finest(("Reading frame")); + }else if (val == CJVMTI_JVMTI_ERROR) { + log.finest("No frame information!"); + return; + }else{ + log.finer("Error reading frame"); + System.exit(0); + } + + + + long methodID = variablesIn.readLong(); + String methodName = readCString(variablesIn); + log.log(Level.FINEST, "Method name is: " + methodName); + long declaringClass = variablesIn.readLong(); + long cPos = variablesIn.getStreamPosition(); // Save where we are before reading in the declaring class + JClass clazz = (JClass) nreadReference(declaringClass); + variablesIn.seek(cPos); // Return to our read position + + + byte depth = variablesIn.readByte(); if (depth == CJVMTI_LOCAL_NATIVECALL) { - log.log(Level.FINEST,"Native call"); - in.seek(startPos + frameSize + 1); - continue; + log.log(Level.FINEST, "Native call"); + JStackFrame jsf = new JStackFrame(); + JLocation loc = new JLocation(); + JMethod jm = model.getMethod(methodID); + loc.linenumber = -1; + loc.method = jm; + loc.setAddress(-1); + loc.filename = clazz.sourceFile; + if (loc.filename == null){ + loc.filename = "nativeCall"; // .. + } + jsf.setLocation(loc); + t.addStackFrame(jsf); + return; } else if (depth == CJVMTI_LOCAL_VARIABLE) { - log.log(Level.FINEST,"Local var"); + log.log(Level.FINEST, "Local var"); } else if (depth == CJVMTI_JVMTI_ERROR) { - log.log(Level.FINEST,"Data unavailable"); - in.seek(startPos + frameSize + 1); - continue; + log.log(Level.FINEST, "Data unavailable"); + return; } - long location = in.readLong(); - log.log(Level.FINEST,"Location is " + location); - // now set up JStackFrame and location + long location = variablesIn.readLong(); + log.log(Level.FINEST, "Location is " + location); + + JStackFrame jsf = new JStackFrame(); JLocation loc = new JLocation(); jsf.setLocation(loc); loc.setAddress(location); + if (clazz != null) { loc.filename = clazz.sourceFile; } + loc.method = model.getMethod(methodID); - // loc.linenumber = loc.method.getLineNumber(location); - loc.linenumber = (int) location; - log.log(Level.FINEST," Line number " + loc.linenumber + " to " + loc.linenumber = loc.method.getLineNumber(location); + log.log(Level.FINEST, " Line number " + loc.linenumber + " to " + location); - int varCount = in.readInt(); - log.log(Level.FINEST,"vars: " + varCount); + int varCount = variablesIn.readInt(); + int slots[] = new int[varCount]; + long lvarReference[] = new long[varCount]; + log.log(Level.FINEST, "vars: " + varCount); + + // Read in all the variable references for (int i2 = 0; i2 < varCount; i2++) { - jsf.addVariable(nreadLocalVars()); + slots[i2] = variablesIn.readInt(); + lvarReference[i2] = variablesIn.readLong(); + } + + // Follow all the variable references + for (int i2 = 0; i2 < varCount; i2++){ + log.finest("Slot "+slots[i2]+" at "+Long.toHexString(lvarReference[i2])); + JLocalVariable jlv = new JLocalVariable(); + jlv.slot = slots[i2]; + long cpos = variablesIn.getStreamPosition(); + jlv.value = nreadReference(lvarReference[i2]); + variablesIn.seek(cpos); + jsf.addVariable(jlv); } t.addStackFrame(jsf); - in.seek(startPos + frameSize + 1); - } else { - log.log(Level.FINEST,"Error " + in.getStreamPosition() + " " - + in.readByte()); - } - } + + } + /** + * Read monitor information + * @param t Thread context + * @throws IOException + */ private void readMonitor(JThread t) throws IOException { - int ownedMonitorCount = in.readInt(); - log.log(Level.FINEST,"Owned monitor count " + ownedMonitorCount); - if (ownedMonitorCount == 0) - return; - + int ownedMonitorCount = variablesIn.readInt(); + log.log(Level.FINEST, "Owned monitor count " + ownedMonitorCount); + if (ownedMonitorCount == 0) return; for (int i = 0; i < ownedMonitorCount; i++) { - long objID = in.readLong(); - nreadReference(objID); + log.finest("Monitor "+i+" of "+ ownedMonitorCount); + long objID = variablesIn.readLong(); + long cPos = variablesIn.getStreamPosition(); // Save current read + nreadReference(objID); // Follow reference + variablesIn.seek(cPos); // Return to read point JMonitor monitor = model.getMonitor(objID); monitor.setObject(monitor.id); monitor.setOwner(t.id); } } + /** + * Get contended monitor information + * @param t Thread context + * @throws IOException + */ private void readContendedMonitor(JThread t) throws IOException { - long contendedObject = in.readLong(); - log.log(Level.FINEST,"Contended object: " + long contendedObject = variablesIn.readLong(); + log.log(Level.FINEST, "Contended object: " + Long.toHexString(contendedObject)); if (contendedObject != CJVMTI_NULL_OBJECT) { JMonitor monitor = model.getMonitor(contendedObject); + long cPos = variablesIn.getStreamPosition(); nreadReference(contendedObject); + variablesIn.seek(cPos); monitor.addWaiter(t.id); monitor.setObject(contendedObject); } } private void nreadThread(long id) throws IOException { - log.log(Level.FINEST,"Reading thread"); - long size = in.readLong(); - String threadname = readCString(in); - long objectRef = in.readLong(); + variablesIn.seek(id); + if (variablesIn.read() == CJVMTI_THREAD){ + log.finest("Reading thread information"); + }else{ + log.fine("Error"); + System.exit(0); + } + String threadname = readCString(variablesIn); + log.finest("thread name "+threadname); + + long objectRef = variablesIn.readLong(); + long cpos = variablesIn.getStreamPosition(); nreadReference(objectRef); + variablesIn.seek(cpos); + JThread t = model.getThread(objectRef); t.threadName = threadname; - log.log(Level.FINEST,t.threadName); + log.log(Level.FINEST, t.threadName); t.groupID = 0; - t.priority = (short) in.readInt(); - t.daemon = (short) in.readByte(); + t.priority = (short) variablesIn.readInt(); + t.daemon = (short) variablesIn.readByte(); readMonitor(t); readContendedMonitor(t); - nreadFrames(t); - in.seek(id + size + 1); + + if (variablesIn.read()==CJVMTI_FRAME){ + log.finest("Reading frames"); + }else{ + log.fine("Error reading frames"); + } + int frameCount = variablesIn.readInt(); + long frameRefs[] = new long[frameCount]; + for (int i = 0; i < frameCount; i ++){ + frameRefs[i] = variablesIn.readLong(); + } + for (int i = 0; i < frameCount; i++){ + log.finest("Reading frame "+i+" of "+frameCount+ " at "+Long.toHexString(frameRefs[i])); + nreadFrames(frameRefs[i], t); + } } - + + /** + * Conveniance method for printing stream position on error + * @param msg + * @throws IOException + */ private void error(String msg) throws IOException { long offset = -1; - try { - offset = in.getStreamPosition(); - } catch (IOException e) { - - } - throw new IOException("at offset " + offset + ": " + msg); + throw new IOException("at offset " + + Long.toHexString(variablesIn.getStreamPosition()) + ": " + msg); } - class VariableValue { - String signature = null; - } + /** + * Get java model + * @return JavaModel + */ public Model getModel() { return model; }