You are viewing a plain text version of this content. The canonical link for it is here.
Posted to kato-commits@incubator.apache.org by mo...@apache.org on 2009/04/08 14:51:47 UTC
svn commit: r763261 - in
/incubator/kato/trunk/trunk/org.apache.kato.example: ./ .settings/ src/
src/org/ src/org/apache/ src/org/apache/kato/ src/org/apache/kato/example/
Author: monteith
Date: Wed Apr 8 14:51:47 2009
New Revision: 763261
URL: http://svn.apache.org/viewvc?rev=763261&view=rev
Log:
Check in an example that shows how to use the Apache Kato API to print out the contents of all the objects and arrays
on a heap.
Added:
incubator/kato/trunk/trunk/org.apache.kato.example/.classpath (with props)
incubator/kato/trunk/trunk/org.apache.kato.example/.project (with props)
incubator/kato/trunk/trunk/org.apache.kato.example/.settings/
incubator/kato/trunk/trunk/org.apache.kato.example/.settings/org.eclipse.jdt.core.prefs (with props)
incubator/kato/trunk/trunk/org.apache.kato.example/src/
incubator/kato/trunk/trunk/org.apache.kato.example/src/org/
incubator/kato/trunk/trunk/org.apache.kato.example/src/org/apache/
incubator/kato/trunk/trunk/org.apache.kato.example/src/org/apache/kato/
incubator/kato/trunk/trunk/org.apache.kato.example/src/org/apache/kato/example/
incubator/kato/trunk/trunk/org.apache.kato.example/src/org/apache/kato/example/ObjectFields.java (with props)
Added: incubator/kato/trunk/trunk/org.apache.kato.example/.classpath
URL: http://svn.apache.org/viewvc/incubator/kato/trunk/trunk/org.apache.kato.example/.classpath?rev=763261&view=auto
==============================================================================
--- incubator/kato/trunk/trunk/org.apache.kato.example/.classpath (added)
+++ incubator/kato/trunk/trunk/org.apache.kato.example/.classpath Wed Apr 8 14:51:47 2009
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/sun160"/>
+ <classpathentry kind="lib" path="/ApacheKatoDependencies/libs/kato.api-head.jar"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
Propchange: incubator/kato/trunk/trunk/org.apache.kato.example/.classpath
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: incubator/kato/trunk/trunk/org.apache.kato.example/.project
URL: http://svn.apache.org/viewvc/incubator/kato/trunk/trunk/org.apache.kato.example/.project?rev=763261&view=auto
==============================================================================
--- incubator/kato/trunk/trunk/org.apache.kato.example/.project (added)
+++ incubator/kato/trunk/trunk/org.apache.kato.example/.project Wed Apr 8 14:51:47 2009
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.apache.kato.example</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
Propchange: incubator/kato/trunk/trunk/org.apache.kato.example/.project
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: incubator/kato/trunk/trunk/org.apache.kato.example/.settings/org.eclipse.jdt.core.prefs
URL: http://svn.apache.org/viewvc/incubator/kato/trunk/trunk/org.apache.kato.example/.settings/org.eclipse.jdt.core.prefs?rev=763261&view=auto
==============================================================================
--- incubator/kato/trunk/trunk/org.apache.kato.example/.settings/org.eclipse.jdt.core.prefs (added)
+++ incubator/kato/trunk/trunk/org.apache.kato.example/.settings/org.eclipse.jdt.core.prefs Wed Apr 8 14:51:47 2009
@@ -0,0 +1,12 @@
+#Tue Apr 07 18:45:08 BST 2009
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
Propchange: incubator/kato/trunk/trunk/org.apache.kato.example/.settings/org.eclipse.jdt.core.prefs
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: incubator/kato/trunk/trunk/org.apache.kato.example/src/org/apache/kato/example/ObjectFields.java
URL: http://svn.apache.org/viewvc/incubator/kato/trunk/trunk/org.apache.kato.example/src/org/apache/kato/example/ObjectFields.java?rev=763261&view=auto
==============================================================================
--- incubator/kato/trunk/trunk/org.apache.kato.example/src/org/apache/kato/example/ObjectFields.java (added)
+++ incubator/kato/trunk/trunk/org.apache.kato.example/src/org/apache/kato/example/ObjectFields.java Wed Apr 8 14:51:47 2009
@@ -0,0 +1,499 @@
+/*******************************************************************************
+ * 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.example;
+
+import java.lang.reflect.Array;
+import java.util.Iterator;
+
+import org.apache.kato.image.CorruptData;
+import org.apache.kato.image.CorruptDataException;
+import org.apache.kato.image.DTFJException;
+import org.apache.kato.image.ImagePointer;
+import org.apache.kato.image.MemoryAccessException;
+import org.apache.kato.java.JavaClass;
+import org.apache.kato.java.JavaField;
+import org.apache.kato.java.JavaHeap;
+import org.apache.kato.java.JavaObject;
+import org.apache.kato.java.JavaRuntime;
+
+/**
+ * This examples walks over all objects on the heap and prints the values
+ * of all of the fields, and the contents of all elements of all the arrays.
+ *
+ * The example starts with walkObjectFields(JavaRuntime), so it's not a complete
+ * example.
+ *
+ *
+ * The following API interfaces are used:
+ * JavaRuntime
+ * JavaHeap
+ * JavaObject
+ * JavaClass
+ * JavaField
+ *
+ * It is useful to consider the classes as being analogues of the Java reflection classes.
+ * The equivalence is:
+ *
+ * JavaObject java.lang.Object
+ * JavaClass java.lang.Class
+ * JavaField java.lang.reflect.Field
+ *
+ * Here is some example output:
+
+JavaObject @ 0x100f7270
+ java/lang/UnsatisfiedLinkError:
+ java/lang/LinkageError:
+ java/lang/Error:
+ java/lang/Throwable:
+ Ljava/lang/Object; backtrace = [Ljava/lang/Object;: @ 0x100f70d8
+ Ljava/lang/String; detailMessage = java/lang/String: @ 0x100f7108java/lang/String: @ 0x100f7108 = "/home/monteith/IBMJava2-142/jre/bin/libCrash.so: /home/monteith/IBMJava2-142/jre/bin/libCrash.so: cannot open shared object file: No such file or directory"
+ Ljava/lang/Throwable; cause = <null reference>
+ [Ljava/lang/StackTraceElement; stackTrace = <null reference>
+ java/lang/Object:
+JavaObject @ 0x100f7290
+ java/lang/String:
+ [C value = [C: @ 0x100f72b0
+ I offset = 0
+ I count = 30
+ I hash = 0
+ java/lang/Object:
+JavaObject @ 0x100f72b0
+ [C[30] = {
+ j,
+ a,
+ v,
+ a,
+ .,
+ l,
+ a,
+ n,
+ g,
+ .,
+ U,
+ n,
+ s,
+ a,
+ t,
+ i,
+ s,
+ f,
+ i,
+ e,
+ d,
+ L,
+ i,
+ n,
+ k,
+ E,
+ r,
+ r,
+ o,
+ r,
+ };
+
+ */
+public class ObjectFields {
+
+ /**
+ * Given a JavaRuntime, print out all of the objects on the heap.
+ *
+ * @param jr JavaRuntime to get objects from
+ */
+ public void walkObjectFields(JavaRuntime jr) {
+
+ /* First get the iterator for all of the heaps.
+ * A JVM's heap may split across different heaps, e.g.
+ * nurseries, system heap, large object heap.
+ */
+ Iterator heaps = jr.getHeaps();
+
+
+ /* What follows is a typical pattern,
+ * iterate, check type, handle data or handle corrupt data,
+ * continue.
+ */
+ while (heaps.hasNext()) {
+ Object next = heaps.next();
+
+ // This is the normal case.
+ if (next instanceof JavaHeap) {
+ walkHeap ((JavaHeap) next);
+ }
+ // As per the JavaDoc, expect CorruptData.
+ else if (next instanceof CorruptData) {
+ // We have a string to print out and an address.
+ System.err.println("Corrupt Heap instance \"" + next + "\"" +
+ pointerToHexString(((CorruptData)next).getAddress()));
+ continue;
+ }
+
+ } // while (heaps.hasNext())
+ }
+
+ /**
+ * Walks over all objects on the heap.
+ *
+ * @param heap JavaHeap to iterate over.
+ */
+ public void walkHeap(JavaHeap heap) {
+ Iterator objects = heap.getObjects();
+
+ // Follow same pattern as walkObjectFields
+ while (objects.hasNext()) {
+ Object next = objects.next();
+
+ /* The heap has only JavaObjects on it. Not JavaClasses,
+ * but JavaObjects of type java/lang/Class will be encountered.
+ */
+ if (next instanceof JavaObject) {
+ JavaObject jObject = (JavaObject) next;
+
+ /* Some objects are arrays, while they are JavaObjects.
+ * They are handled differently.
+ */
+ try {
+ if (jObject.isArray()) {
+ walkArray (jObject);
+ } else {
+ walkObject (jObject);
+ }
+
+ // Even determining whether or not the JavaObject is an array has difficulties.
+ } catch (CorruptDataException e) {
+ System.err.println("Corrupt data exception calling jObject.isArray() at "+
+ pointerToHexString(jObject.getID()));
+ e.printStackTrace();
+ }
+ }
+
+ /* Iterators return a mix of objects - either what you expected
+ * or a CorruptData object.
+ */
+ else if (next instanceof CorruptData) {
+ // We have a string to print out and an address.
+ System.err.println("Corrupt Heap instance \"" + next + "\"" +
+ pointerToHexString(((CorruptData)next).getAddress()));
+ continue;
+ }
+
+
+ } // while (objects.next()
+ }
+
+ /**
+ * Prints out all of the values of the fields in an object, along with
+ * identifying information of the type itself.
+ *
+ * <br/>To print out the values of an objects fields, we do the following:
+ *
+ * <ol>
+ * <li>Get the object's type - a JavaClass.</li>
+ * <li>Retrieve the fields (JavaField) from that JavaClass.</li>
+ * <li>Call the JavaField's get methods, passing the JavaObject, printing out the values.</li>
+ * <li>Get the type's superclass (another JavaClass), if it's not null, repeat from 2.</li>
+ * </ol>
+ *
+ * @param jObject A JavaObject
+ */
+ public void walkObject(JavaObject jObject) {
+
+
+ // Just identify the object by its ID - this would the address on the heap.
+ System.out.println("JavaObject @ " + pointerToHexString(jObject.getID()));
+ // Handle indentation.
+ String prefix = "\t";
+
+ /* Get the type of this object.
+ * A common mistake is to call "Class Object.getClass()".
+ *
+ * If we can't get the type, print error and return - there is nothing
+ * to be done here. It's important that the iterator either finishes or
+ * continues past the bad object.
+ */
+ JavaClass clazz;
+ try {
+ clazz = jObject.getJavaClass();
+ } catch (CorruptDataException e) {
+ System.err.println(prefix+"Error getting JavaClass");
+ e.printStackTrace();
+ return;
+ }
+
+ /* The fields in a class are only the fields for that class.
+ * The superclasses fields must retreived from the superclasses.
+ *
+ * Some classes don't have a superclass - null is used to indicate this.
+ */
+ while (clazz != null) {
+ // print out the name of the class and the the fields.
+ try {
+ System.out.println( prefix + clazz.getName() +":");
+ prefix += " ";
+
+ Iterator fields = clazz.getDeclaredFields();
+
+ /* Print out all fields for this class.
+ */
+ while (fields.hasNext()) {
+ Object nextField = fields.next();
+
+ if (nextField instanceof JavaField) {
+ printField(prefix, (JavaField) nextField, jObject);
+ } else if (nextField instanceof CorruptData) {
+ System.err.println("Error getting field. " + nextField);
+ }
+ } // while (fields.hasNext())
+ } catch (DTFJException e) {
+ System.err.println("Error printing out fields.");
+ e.printStackTrace();
+ }
+
+ // Get the next superclass.
+ try {
+ clazz = clazz.getSuperclass();
+ } catch (CorruptDataException e) {
+
+ e.printStackTrace();
+ break;
+ }
+
+ } // while (class != null)
+ }
+
+ /**
+ * Print out the content of one field.
+ * Only prints out instance fields. Will return if a
+ * static field is passed.
+ *
+ * @param prefix Pad out message
+ * @param field The field to print
+ * @param object The object to print out
+ * @throws CorruptDataException if something goes wrong
+ * @throws MemoryAccessException
+ */
+ private void printField(String prefix, JavaField field, JavaObject object) throws CorruptDataException, MemoryAccessException {
+
+ /* Modifier is fully qualified to indicate that some constants are not held by the API,
+ * but reused from the existing reflection API.
+ * This is testing the field to see if it is static. The getModifiers method is
+ * held within the JavaMember interface. Here the resemblance to Java reflection is more
+ * pronounced.
+ */
+ if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) {
+ return;
+ }
+
+ /* Get the value of a field. This call will suit for all
+ * field types, primitives and references.
+ * A java.lang.Integer instance would be returned as a JavaObject, not as an Integer,
+ * but a primitive int field will be returned as an Integer.
+ * There are methods that can be used to return the primitives directly, the
+ * JavaMember.getSignature() methods would have to be used in order to determine the
+ * field's type.
+ *
+ */
+ Object fieldValue = field.get(object);
+
+ String valueString = "";
+
+ // Format the field's value.
+ if(fieldValue == null) {
+ valueString = "<null reference>";
+
+ // Most of the primitive fields can be handled as Number instances.
+ } else if (fieldValue instanceof Number) {
+ valueString = fieldValue.toString();
+ } else if (fieldValue instanceof Character) {
+ valueString = "`" + (Character)fieldValue + "'";
+ } else if (fieldValue instanceof Boolean) {
+ valueString = ((Boolean) fieldValue).booleanValue() ? "true" : "false";
+ } else if (fieldValue instanceof JavaObject) {
+ // Note how we have to get an instance of the object to know anything about it.
+ JavaObject reference = (JavaObject) fieldValue;
+
+ // classname: @ 0xadddress
+ valueString = reference.getJavaClass().getName() + ": @ " + pointerToHexString(reference.getID());
+
+ /* We can get the actual String as it would appear if printed on the running JVM using
+ * the JavaField.getString() method.
+ * To do this, we have to identify the object referenced as a java.lang.String.
+ * We use a string comparision against the referenced object's class name rather than using
+ * JavaField.getSignature(), as that could simply be a java.lang.Object reference.
+ *
+ * This is the only means of translating a JavaObject into a String instance without
+ * examining the referenced JavaObject fields using the API.
+ */
+ if ("java/lang/String".equals(reference.getJavaClass().getName())) {
+ valueString += valueString +" = \"" + field.getString(object) + "\"";
+ }
+
+ }
+ // The JavaField.get() method doesn't return CorruptData - it throws CorruptDataException and
+ // MemoryAccessException
+
+ /* Print out the value of the field, prefixed by its signature and name.
+ * The signature will come out in the internal, compact format. This could
+ * be expanded with more code into Java language style.
+ *
+ * For example, a string would be "Ljava/lang/String;", a string array
+ * would be "[Ljava/lang/String;", a byte would be "B", a boolean array
+ * would be "[Z".
+ *
+ */
+ System.out.println(prefix + field.getSignature() + " " +
+ field.getName() + " = " + valueString);
+ }
+
+ /**
+ * Print out the contents of an array.
+ *
+ * @param jObject JavaObject of an array.
+ */
+ public void walkArray(JavaObject object) {
+ // Just identify the object by its ID - this would the address on the heap.
+ System.out.println("JavaObject @ " + pointerToHexString(object.getID()));
+ // Handle indentation.
+ String prefix = "\t";
+ String className;
+
+ JavaClass clazz;
+ try {
+ clazz = object.getJavaClass();
+ } catch (CorruptDataException e) {
+ System.err.println("Unable to determine array's JavaClass. aborting");
+ e.printStackTrace();
+ return;
+ }
+
+ // The class name is needed to determine the element types
+ try {
+ className = clazz.getName();
+ } catch (CorruptDataException e) {
+ System.err.println("Error getting Array class name.");
+ e.printStackTrace();
+ return;
+ }
+
+
+ int arraySize = 0;
+
+ /* This gets the number of elements in the array.
+ * It should not be confused with JavaObject.getSize() which
+ * is the size of the array on the heap.
+ */
+ try {
+ arraySize = object.getArraySize();
+ } catch (CorruptDataException e) {
+ System.err.println("Unable to get object size.");
+ e.printStackTrace();
+ return;
+ }
+
+ String componentName;
+ try {
+ componentName = clazz.getComponentType().getName();
+ } catch (CorruptDataException e) {
+ System.err.println("Unable to determine component type name. Quitting.");
+ e.printStackTrace();
+ return;
+ }
+
+ Object arrayCopy;
+
+ /* Create an instance of the array that JavaObject.arraycopy()
+ * will copy into. Must be of correct type.
+ *
+ * There exist classes that directly represent the primitive types.
+ * See Javadoc for java.lang.Class.
+ *
+ * i.e. an actual class called "int", not "java/lang/Integer".
+ */
+ if ("boolean".equals(componentName)) {
+ arrayCopy = new boolean[arraySize];
+ } else if ("byte".equals(componentName)) {
+ arrayCopy = new byte[arraySize];
+ } else if ("char".equals(componentName)) {
+ arrayCopy = new char[arraySize];
+ } else if ("short".equals(componentName)) {
+ arrayCopy = new short[arraySize];
+ } else if ("int".equals(componentName)) {
+ arrayCopy = new int[arraySize];
+ } else if ("long".equals(componentName)) {
+ arrayCopy = new long[arraySize];
+ } else if ("float".equals(componentName)) {
+ arrayCopy = new float[arraySize];
+ } else if ("double".equals(componentName)) {
+ arrayCopy = new double[arraySize];
+ } else {
+ // Anything element that is not a primitive must be a reference type.
+ arrayCopy = new JavaObject[arraySize];
+ }
+
+ /* Copy the contents of the JavaObject array into the array we prepared earlier.
+ * This is the only way to get the values of an array in a dump.
+ */
+ try {
+ object.arraycopy(0, arrayCopy, 0, arraySize);
+ } catch (CorruptDataException e) {
+ e.printStackTrace();
+ return;
+ } catch (MemoryAccessException e) {
+ e.printStackTrace();
+ return;
+ } catch (IllegalArgumentException e){
+ e.printStackTrace();
+ return;
+ } catch (IndexOutOfBoundsException e) {
+ e.printStackTrace();
+ return;
+ }
+
+ /* Go through every element in the copy of the array and print out its contents.
+ * This example uses java.lang.Array.get() to make this easy to handle generically.
+ *
+ * Object references - JavaObjects - are only printed out at the type name @ an address.
+ * We don't print out subarrays - they will be encountered later in the heap anyhow.
+ */
+ System.out.println("\t" + className + "[" + arraySize +"] = {");
+ for (int cnt=0; cnt < arraySize; cnt++) {
+ Object obj = Array.get(arrayCopy, cnt);
+
+ if (obj == null) {
+ System.out.println("\t\tnull,");
+ } else if (obj instanceof JavaObject) {
+ JavaObject refObj = (JavaObject) obj;
+ try {
+ System.out.println("\t\t" + refObj.getJavaClass().getName()+ " @ "+
+ pointerToHexString(refObj.getID())+",");
+ } catch (CorruptDataException e) {
+ System.err.println("\t\t CorruptDataException while printing out array element");
+ e.printStackTrace();
+ }
+ } else {
+ System.out.println("\t\t"+obj+",");
+ }
+ }
+ System.out.println("\t};");
+ }
+
+ /**
+ * Takes ImagePointer and returns it as a hex string. Perhaps this should be defined
+ * behaviour for ImagePointer.toString().
+ * @param pointer ImagePointer
+ * @return Address of pointer as a hex string prefixed with "0x"
+ */
+ public static String pointerToHexString(ImagePointer pointer) {
+ return "0x"+Long.toHexString(pointer.getAddress());
+ }
+}
Propchange: incubator/kato/trunk/trunk/org.apache.kato.example/src/org/apache/kato/example/ObjectFields.java
------------------------------------------------------------------------------
svn:mime-type = text/plain