incubator-kato-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From monte...@apache.org
Subject svn commit: r805906 - /incubator/kato/trunk/org.apache.kato/kato.docs/src/docbkx/chapters/examples.xml
Date Wed, 19 Aug 2009 18:07:50 GMT
Author: monteith
Date: Wed Aug 19 18:07:49 2009
New Revision: 805906

URL: http://svn.apache.org/viewvc?rev=805906&view=rev
Log:
Add example "ObjectFields". This is the previous example with new annotations and targeted
against the new API.

Modified:
    incubator/kato/trunk/org.apache.kato/kato.docs/src/docbkx/chapters/examples.xml

Modified: incubator/kato/trunk/org.apache.kato/kato.docs/src/docbkx/chapters/examples.xml
URL: http://svn.apache.org/viewvc/incubator/kato/trunk/org.apache.kato/kato.docs/src/docbkx/chapters/examples.xml?rev=805906&r1=805905&r2=805906&view=diff
==============================================================================
--- incubator/kato/trunk/org.apache.kato/kato.docs/src/docbkx/chapters/examples.xml (original)
+++ incubator/kato/trunk/org.apache.kato/kato.docs/src/docbkx/chapters/examples.xml Wed Aug
19 18:07:49 2009
@@ -377,7 +377,7 @@
 This code prints out the names of the libraries that were loaded by the process.
 This should include any JNI libraries that were configured. Note that it is also
 possible to determine where in memory these libraries have been mapped using the
-<methodname>ImageModule.
+<methodname>ImageModule</methodname>.
 . This can
 be used to identify where a thread might have crashed.
 			
@@ -466,4 +466,599 @@
 
 	</para>
 	</sect2>
+
+
+	<sect2 xml:id="api.examples.fields">
+	<title>Retrieving Object Fields</title>
+	<para>
+	This example demonstrates how object instance fields and array elements are accessed
+	using the API. 
+	</para>
+	<para>
+	The follow is the declaration for this example class. It extends a class that will
+	call the <methodname>analyzeRuntime(JavaRuntime)</methodname> method with a
valid
+	<classname>JavaRuntime</classname>. Some applications and implementations will
only be
+	interested in the Java API.
+	
+<example xml:id="api.examples.fields.declaration">
+<title>Object fields class declaration</title>
+<programlisting>
+<![CDATA[	
+package org.apache.kato.examples;
+
+import java.lang.reflect.Array;
+
+import javax.tools.diagnostics.image.CorruptDataException;
+import javax.tools.diagnostics.image.ImagePointer;
+import javax.tools.diagnostics.image.KatoException;
+import javax.tools.diagnostics.image.MemoryAccessException;
+import javax.tools.diagnostics.runtime.java.JavaClass;
+import javax.tools.diagnostics.runtime.java.JavaField;
+import javax.tools.diagnostics.runtime.java.JavaHeap;
+import javax.tools.diagnostics.runtime.java.JavaObject;
+import javax.tools.diagnostics.runtime.java.JavaRuntime;
+
+public class ObjectFields extends RuntimeAnalyzer {
+]]>
+</programlisting>
+</example>		
+
+The <methodname>analyzeRuntime</methodname> method walks over the heaps within
the JVM.
+While Java programmers will be used to the concept of the heap, the API allows a number
+of heaps to be accessed in a single JVM. It is expected the different heaps will have 
+different garbage collection policies and that each heap will be identified with a
+descriptive name through <methodname>JavaHeap.getName()</methodname>. The number
of
+heaps and their names is implementation specific, but there must be at least one in a
+running JVM.
+
+<example xml:id="api.examples.fields.examineheaps">
+<title>Iterate over heaps</title>
+<programlisting>
+<![CDATA[		
+	public void analyzeRuntime(JavaRuntime jr) {
+		for (JavaHeap heap : jr.getHeaps()) {
+				walkHeap (heap);
+		} 		
+	}
+	
+]]>
+</programlisting>
+</example>		
+
+<para>
+This section of code retrieves each object from the heap. For API implementations
+backed by a core file, the objects will probably be retrieved in order from lowest
+address in memory to the highest, but there is no relationship between 
+<classname>JavaObject</classname> list indexes and the results of <methodname>JavaObject.getID()</methodname>
+that can be relied upon by callers of the API.
+</para>
+<para>
+The <classname>JavaObject</classname> retrieved has to be tested to see if it
is
+an array or an ordinary object as they are handled differently.
+</para>
+
+
+<example xml:id="api.examples.fields.objects">
+<title>Iterate over Objects</title>
+<programlisting>
+<![CDATA[
+	public void walkHeap(JavaHeap heap) {
+		for (JavaObject jObject : heap.getObjects()) {
+
+			try {
+				if (jObject.isArray()) {
+					walkArray (jObject);
+				} else {
+					walkObject (jObject);
+				}
+
+			} catch (CorruptDataException e) {
+				System.err.println("Corrupt data exception calling jObject.isArray() at "+
+						pointerToHexString(jObject.getID()));
+				e.printStackTrace();
+			}
+		} 
+	}
+
+]]>
+</programlisting>
+</example>		
+
+<para>
+This method takes a <classname>JavaObject</classname> and prints out the
+values of all of the instance fields (not the static fields).
+</para>
+
+<example xml:id="api.examples.fields.object">
+<title>Print object fields</title>
+<programlisting>
+<![CDATA[
+	
+	/**
+	 * Prints out all of the values of the fields in an object, along with
+	 * identifying information of the type itself.
+	 * 
+	 * @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";
+]]>
+</programlisting>
+</example>		
+
+<para>
+Each object in an instance of a class, so here the <classname>JavaClass</classname>
is retrieved.
+This is equivalient to the following in Java:
+
+<programlisting>
+Class java.lang.Object.getClass();
+</programlisting>
+
+Implementors should ensure that the API returns the equivalent <classname>JavaClass</classname>.

+
+</para>
+
+<example xml:id="api.examples.fields.getjavaclass">
+<title>Get the object's type</title>
+<programlisting>
+<![CDATA[
+		
+		// Get the type of this object.		
+		JavaClass clazz;
+		try {
+			clazz = jObject.getJavaClass();
+		} catch (CorruptDataException e) {
+			System.err.println(prefix+"Error getting JavaClass");
+			e.printStackTrace();
+			return;
+		}
+]]>
+</programlisting>
+</example>		
+
+<para>
+A class will only report its fields, the superclasses must be retrieved in order to
+retrieve <emphasis>their</emphasis> fields. This while loop retrieves each superclass
+until the superclass is null, which will be returned by the <classname>java.lang.Object</classname>
+class.
+</para>
+
+<example xml:id="api.examples.fields.superclasses">
+<title>Iterate up class hierarchy</title>
+<programlisting>
+<![CDATA[		
+		while (clazz != null) {
+			// print out the name of the class and the the fields.
+			try {
+				System.out.println( prefix + clazz.getName() +":");
+				prefix += "  ";
+]]>
+</programlisting>
+</example>		
+
+<para>
+This code retrieves each field from a <classname>JavaClass</classname>.
+This is equivalent to the following method in Java reflection:
+<programlisting>
+Field[] java.lang.Class.getDeclaredFields()
+</programlisting>
+
+This should return all fields, even synthetic fields.
+</para>
+
+<example xml:id="api.examples.fields.getfields">
+<title>Print out each field</title>
+<programlisting>
+<![CDATA[		
+		
+				for (JavaField nextField : clazz.getDeclaredFields()) {					
+					printField(prefix, nextField, jObject);						
+				}
+			} catch (KatoException e) {
+				System.err.println("Error printing out fields.");
+				e.printStackTrace();
+			}
+]]>
+</programlisting>
+</example>		
+
+<para>
+Here the next superclass is retrieved. The loop is terminated by the
+<code>break</code> if the superclass couldn't be retrieved.
+</para>
+
+<example xml:id="api.examples.fields.superclass">
+<title>get next superclass</title>
+<programlisting>
+<![CDATA[		
+			try {
+				clazz = clazz.getSuperclass();
+			} catch (CorruptDataException e) {				
+				e.printStackTrace();
+				break;
+			}
+			
+		} // while (class != null)
+	}
+	
+]]>
+</programlisting>
+</example>		
+
+<para>
+This method demonstrates how to print out an instance field.
+Note that the <classname>JavaObject</classname> is passed as it must passed
+to the <classname>JavaField</classname> in order to actually retrieve the value
of the field
+in that instance.
+</para>
+
+<example xml:id="api.examples.fields.printfields">
+<title>Print fields class</title>
+<programlisting>
+<![CDATA[			
+	private void printField(String prefix, JavaField field, JavaObject object) throws CorruptDataException,
MemoryAccessException {
+]]>
+</programlisting>
+</example>		
+
+<para>
+It is not worth printing out the class fields for each instance of the class on the heap,
+so the field is tested to see if it is static. The following method call retrieves
+the modifiers (<code>public</code>, <code>static</code>, <code>protected</code>,
etc.)
+from the <classname>JavaField</classname> and then uses reflection to test for
<code>static</code>
+being set. Callers of the API should not assume that <methodname>JavaField.getModifiers()</methodname>
+only returns the bits defined in <classname>java.lang.reflect.Modifier</classname>
- always test
+with the appropriate bitmasks or use the functions provided in <classname>Modifier</classname>.
+</para>
+
+<example xml:id="api.examples.fields.modifiers">
+<title>Testing JavaField.getModifiers()</title>
+<programlisting>
+<![CDATA[		
+
+		if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) {
+			return;
+		}
+]]>
+</programlisting>
+</example>		
+
+<para>
+There are a number of methods provided by <classname>JavaField</classname> to
retrieve
+the field value. The most generic is <methodname>JavaField.get(JavaObject)</methodname>
+which returns an <classname>Object</classname>.
+</para>
+
+<example xml:id="api.examples.fields.getvalue">
+<title>Getting the value of a field</title>
+<programlisting>
+<![CDATA[		
+		Object fieldValue = field.get(object);
+		
+		String valueString = "";
+]]>
+</programlisting>
+</example>		
+
+<example xml:id="api.examples.fields.null">
+<title>JavaField.get() returns null</title>
+<programlisting>
+<![CDATA[		
+		// Format the field's value. 
+		if(fieldValue == null) {
+			valueString = "<null reference>";
+			
+]]>
+</programlisting>
+</example>		
+
+<para>
+As <methodname>JavaField.get(Object)</methodname> can return
+any type, primitive fields values are returned in instances of <classname>Number</classname>
+or <classname>Character</classname>. For instance, an <code>int</code>
would be returned as an
+instance of <classname>java.lang.Integer</classname>. This can't be confused
with fields that
+are references to <classname>java.lang.Integer</classname> instances as they
would be represented
+by <classname>JavaObject</classname>.  
+</para>
+
+<example xml:id="api.examples.fields.number">
+<title>Boxed numbers</title>
+<programlisting>
+<![CDATA[
+		} 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";
+]]>
+</programlisting>
+</example>		
+
+<para>
+<methodname>JavaField.get()</methodname> is the means by which references to
other objects
+are also retrieved. This program just retrieves the referred object's class name and its
+ID. It is important to remember that the signature of the field is expected to be an appropriate
+type for the objects that can be retrieved from it. A field signature would be either the
+same type as an object retrieved from it, an interface or super-interface, or a super class.
+</para>
+
+<example xml:id="api.examples.fields.objrefs">
+<title>Retrieving an object reference</title>
+<programlisting>
+<![CDATA[			
+		} 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());
+]]>
+</programlisting>
+</example>		
+
+<para>
+The following code tests the object type to see if it is a Java String instance. 
+The <classname>JavaClass</classname> representing <classname>java.lang.String</classname>
could be cached
+and compared against the objects classes, but instead we compare against the name of the
object's class.
+The method <methodname>JavaField.getString()</methodname> is used to retrieve
the <classname>JavaObject</classname>
+as an instance of <classname>java.lang.String</classname> in the running JVM.

+</para>
+
+<example xml:id="api.examples.fields.stringvalue">
+<title>Retrieving a string field</title>
+<programlisting>
+<![CDATA[			
+			if ("java/lang/String".equals(reference.getJavaClass().getName())) {
+				valueString += valueString +" = \"" + field.getString(object) + "\"";
+			}
+			
+		}
+
+		System.out.println(prefix + field.getSignature() + " " + 
+				field.getName() + " = " + valueString);		
+	}
+
+]]>
+</programlisting>
+</example>		
+
+<para>
+This method deals only with arrays.
+</para>
+
+<example xml:id="api.examples.fields.walkarray">
+<title>Method for printing out array contents</title>
+<programlisting>
+<![CDATA[
+	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 className;
+]]>
+</programlisting>
+</example>		
+
+<para>
+All instances of <classname>JavaObject</classname> have a <classname>JavaClass</classname>
+with a name. For arrays, this follows the JNI conventions.
+</para>
+
+<example xml:id="api.examples.fields.arrayclass">
+<title>All objects have classes</title>
+<programlisting>
+<![CDATA[		
+		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;
+		}
+
+]]>
+</programlisting>
+</example>		
+
+<para>
+Each array describes the number of elements it contains. It is
+important to call <methodname>getArraySize()</methodname> and not
+<methodname>getSize()</methodname> as the latter returns the size
+of the object on the heap.
+</para>
+
+<example xml:id="api.examples.fields.arraysize">
+<title>Get number of array elements</title>
+<programlisting>
+<![CDATA[
+		int arraySize = 0;
+ 
+		try {
+			arraySize = object.getArraySize();
+		} catch (CorruptDataException e) {
+			System.err.println("Unable to get object size.");
+			e.printStackTrace();
+			return;
+		}		
+]]>
+</programlisting>
+</example>		
+
+<para>
+An array's class should be able to report the type of it's elements.
+We use this call to determine the type of array to receive the contents of
+the array.
+</para>
+
+<example xml:id="api.examples.fields.componenttype">
+<title>Getting the type of the array elements</title>
+<programlisting>
+<![CDATA[
+		String componentName;
+		try {
+			componentName = clazz.getComponentType().getName();
+		} catch (CorruptDataException e) {
+			System.err.println("Unable to determine component type name. Quitting.");
+			e.printStackTrace();
+			return;
+		}
+		]]>
+</programlisting>
+</example>		
+
+<para>
+Arrays elements are accessed on an individual basis. Instead,
+their contents are copied to real arrays.
+This code demonstrates that there are <classname>JavaClass</classname> for
+primitive types, in the same way there is in reflection. These names
+are used to create primitive arrays of the correct type.
+</para>
+
+<example xml:id="api.examples.fields.destarray">
+<title>Creating array of correct type</title>
+<programlisting>
+<![CDATA[
+		Object arrayCopy;
+		
+		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 {
+]]>
+</programlisting>
+</example>		
+
+<para>
+If an array is not an array of primitives, it must be an array
+of objects. As there is no means of converting a <classname>JavaObject</classname>
+into a "real" object, an array of <classname>JavaObject</classname> must suffice.
+This will also retrieve subarrays if the array was a multidimensional array.
+</para>
+
+<example xml:id="api.examples.fields.objectarray">
+<title>Array of JavaObjects as destination</title>
+<programlisting>
+<![CDATA[
+			arrayCopy = new JavaObject[arraySize];
+		}
+							
+]]>
+</programlisting>
+</example>
+
+<para>
+The method <methodname>JavaObject.arraycopy</methodname> is used to copy array
elements
+in the same way as <methodname>java.lang.System.arraycopy()</methodname>. 
+Implementors and those writing applications using this method call should take care as arrays
+can be extremely large, potentially larger than the JVM's heap size. If a fraction of an
array
+is asked for, that is all that should be allowed in memory.
+</para>
+
+<example xml:id="api.examples.fields.arraycopy">
+<title>Copying array contents</title>
+<programlisting>
+<![CDATA[
+		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;
+		}
+		
+]]>
+</programlisting>
+</example>		
+
+<para>
+This code prints out the contents of the array elements. The <methodname>java.lang.Array.get()</methodname>
+method is used to retrieve elements from the array in a generic fashion. If <code>null</code>
is
+retrieved, that is printed, otherwise if it is an object the type and address of the object
is printed
+and failing that it must be an autoboxed primitive that can be printed out using its <methodname>toString()</methodname>.

+</para>
+
+<example xml:id="api.examples.fields.arrayelements">
+<title>Printing out array elements</title>
+<programlisting>
+<![CDATA[
+		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};");
+	}
+
+]]>
+</programlisting>
+</example>		
+
+<para>
+This is a helper function to get a standardized representation for <classname>ImagePointer</classname>.
+</para>
+
+<example xml:id="api.examples.fields.imagepointer">
+<title>Convert ImagePointer to a hex address</title>
+<programlisting>
+<![CDATA[
+	public static String pointerToHexString(ImagePointer pointer) {
+		return "0x"+Long.toHexString(pointer.getAddress());
+	}
+}
+]]>
+</programlisting>
+</example>		
+	
+
+	</para>
+	</sect2>
 </sect1>



Mime
View raw message