0N/AJavaScript interface to Hotspot Serviceability Agent
0N/A<
h1>JavaScript interface to Hotspot Serviceability Agent</
h1>
0N/AServiceability Agent (SA) provides Java API and tools to diagnose HotSpot Virtual Machine and
0N/AJava apps running on it. SA is a snapshot debugger -- can be used to observe state of a frozen java process or java core dump.
0N/A<
h2>Existing SA APIs</
h2>
0N/AThere are two application programmer interfaces (APIs) for SA:
0N/A<
dt>1. Private java API
0N/AThis tries to mimic hotspot VM's internal C++ classes and methods. Because VM data structures
0N/Aare a moving target, this API can never be 'stable'! Besides, to use SA's private API knowledge of
0N/AHotSpot code base is essential.
0N/A<
dt>2. SA-JDI -- Java Debugger Interface read-only subset API
0N/AThis is read-only subset of JDI (Java Debugger Interface)
0N/AThis is a standardized interface to get java level state of a java process or java core dump. While this
0N/Ainterface is useful, this misses parts of java level state from target process or core such as
0N/A<
li>heap walking interface -- only objects traceable to static variables (of classes) and local
0N/Avariables of stack frames can be accessed.
0N/A<
li>re-constructing .class from debuggee are missing.
0N/A<
li>re-constructing object mirrors for Java objects of the debuggee.
0N/A<
h2>SA Scripting interface</
h2>
0N/ATraditionally, platform debuggers such as dbx, gdb and Solaris mdb (Module Debugger), provide a scripting
0N/Alanguage interface. Scripting language interface provides easy-to-use, dynamically typed
0N/Ainterface to access data structures from debuggee. dbx and mdb even allow user to write
0N/AC/C++ modules to extend the scripting language commands.
0N/ASA provides SOQL - Simple Object Query Language -- a SQL-like query language to access
0N/AJava heap as an object database. SA's main GUI (HSDB) also exposes scripting interface of underlying debugger such as dbx, windbg.
0N/ABut to use this interface, user has to learn scripting interface of multiple debugger back-ends such as dbx, windbg.
0N/AAnd these scripting interfaces are 'raw' in the sense that no java state is exposed -- only C/C++ state of VM is exposed.
0N/AHigher level SA services are not available through scripting interface.
0N/A<
b>jsdb -- JavaScript Debugger</
b> attempts to provide JavaScript interface to SA.
0N/A<
li>high-level hotspot (and SA) independent scripting interface
0N/A<
li>low-level SA-aware scripting interface.
0N/A<
h2>High level interface (Java State)</
h2>
0N/AThis command line utility attaches to Java process or core file or remote debug server and waits for user input.
0N/AThis shell supports the following global functions and objects in addition to the standard JavaScript functions and
0N/A<
h3>jdsb globals</
h3>
0N/Afunction that returns the address of the Java object as a string
0N/Afunction that returns the JavaScript object that represents class object of the Java object
0N/AdumpClass(jclass,[dir])
0N/Afunction that writes .class for the given Java Class. Optionally (second arg) accepts the directory where the
0N/A.class has to be written.
0N/Afunction that prints help message for global functions and objects
0N/AidentityHash(jobject)
0N/Afunction that returns the identity hashCode of the Java object
0N/Afunction that returns a local mirror of the Java object.
0N/Aload([file1, file2,...])
0N/Afunction that loads zero or more JavaScript file(s). With no arguments, reads <
stdin> for
0N/Afunction that converts a string address into Java object
0N/Afunction that returns the owner thread of this monitor or null
0N/Afunction that returns the size of Java object in bytes
0N/Astaticof(jclass, field)
0N/Afunction that returns the value of given field of the given Java class
0N/Aprint(expr1, expr2,...)
0N/Afunction that prints zero or more JavaScript expressions after converting those as strings
0N/Aprintln(expr1, expr2..)
0N/Afunction that same as print, but prints a newline at the end
0N/Afunction that reads a single line from standard input
0N/Afunction that quits the interactive load call as well as the shell
0N/Avariable -- a JavaScript object that represents the target jvm that is being debugged
0N/Ajvm object supports the following read-only properties.
0N/Aarray of Java threads from the debuggee
0N/Aobject representing the heap of the debuggee
0N/Astring value that is either "Server" or "Client" or "Core" -- the flavour of debuggee VM
0N/Astring value of bootclasspath of the debuggee
0N/Aname-value pairs (JavaScript associative array) of Java System properties of the debuggee
0N/Aint value -- 32 for 32 bit debuggee, 64 for 64 bit debuggee
0N/Ainternal build info string from debuggee
0N/Aname-value pairs (JavaScript associative array) of JVM command line flags of the debuggee
0N/Astring value of classpath of the debuggee
0N/Astring value of
user.dir System property of the debuggee
0N/Aheap object represents Java heap of the debuggee VM
0N/AFunction or property name
0N/Abyte size of capacity of the heap
0N/Abyte size of used portion (of live objects) of the heap
0N/AforEachObject(func, [class], [include subtypes -- true|false])
0N/AThis function accepts a callback function 'func' and optionally class name and boolean arguments.
0N/AThis function calls the callback for each Java object in the debuggee's heap. The optional class
0N/Aargument may be used to receive objects of given class only. The third arguments specifies whether
0N/Ato include objects of subtype of given class [or interface] or not. The default value of class is "
java.
lang.
Object"
0N/Aand and that of the third argument is true.
i.e., by default all objects are included.
0N/AforEachClass(func, [initiating loader -- true|false])
0N/AThis function accepts a callback function 'func'. This function iterates through the classes of the debuggee and calls the
0N/Acallback for each class. The second parameter tells whether to pass initiating loader to the iterator callback or not.
0N/A<
h3>Accessing Java objects and arrays in script</
h3>
0N/AFrom a given Java object, we can access all fields of the Java object by usual '.' operator.
i.e., if you got a Java object
0N/Aobjects can be accessed by length property. And array indexing follows usual syntax.
i.e., n'th element of array 'a' is
0N/AThis is a JavaScript array of Java threads of the debuggee. As usual, 'length' property tells the number of threads and individual
0N/Athreads may be accessed by index operator --
i.e,
jvm.threads[0] returns the first thread.
0N/A<
h3>thread object</
h3>
0N/AIn addition to the fields of
java.
lang.
Thread (or subclass) fields, thread objects have two additional properties.
0N/A<
li>frames -- array of stack frame objects
0N/A<
li>monitors -- array of monitor objects owned by the thread
0N/A<
h3>stack frame object</
h3>
0N/AObject representing 'this' of the current frame [will be null for static methods]
0N/Aname-value pairs of local variables [JavaScript associative array]
0N/AJava source line number at which the frame is executing
0N/Abyte code index of the bytecode that the frame is executing
0N/Athread to which this frame belongs
0N/AJava method that the frame is executing
0N/A<
h3>method object</
h3>
0N/Amethod object represents a Java method of debuggee
0N/Aboolean - true for static methods and false for non-static methods
0N/Aboolean - true for synchronized methods and false for non-synchronized methods
0N/Aboolean - true for native methods and false for non-native methods
0N/Aboolean - true for protected methods and false for non-protected methods
0N/Aboolean - true for private methods and false for non-private methods
0N/Aboolean - true for Javac generated synthetic methods and false for non-synthetic methods
0N/Aboolean - true for package-private methods and false for non-package-private methods
0N/Aboolean - true for public methods and false for non-public methods
0N/Aan object that represents Class that contains this method
0N/Astring -- signature of this method
0N/Aboolean - true for obsolete (hotswapped) methods and false for non-obsolete methods
0N/Aboolean - true for strictfp methods and false for non-strictfp methods
0N/Aboolean - true for final methods and false for non-final methods
0N/Astring - name of this method
0N/A<
h3>class object</
h3>
0N/AA class object represents loaded Java class in debuggee VM. This represents
java.
lang.
Class instance in the debuggee.
0N/Aclass object representing super class of this class
0N/Aboolean -- is the current class an array class?
0N/Aboolean -- is the current class static or not
0N/Aboolean -- is the current class an interface
0N/Aboolean -- is the current class abstract or not
0N/Aboolean -- is the current class protected or not
0N/Aboolean -- is the current class private or not
0N/Aboolean -- is the current class package private or not
0N/Aboolean -- is the current class synthetic or not
0N/Aobject that represents ClassLoader object that loaded the current class
0N/Aarray of static and instance fields of the current class
0N/Aprotection domain to which current class belongs
0N/Aboolean -- is the current class public or not
0N/Aarray of signers for current class
0N/Astring -- name of the source file for current class
0N/Aarray -- interfaces implemented by current class
0N/Aboolean -- is the current class strictfp or not
0N/Aarray of methods (static and instance) of the current class
0N/Aboolean -- is the current class final or not
0N/Aname-value pairs (JavaScript associate array) of static fields of the current class
0N/A<
h3>field object</
h3>
0N/Afield represents a static or instance field of some class in debuggee
0N/Aboolean -- is this field a static field?
0N/Aclass that owns this field
0N/Astring signature of this field
0N/Aboolean - is this field a protected field or not?
0N/Aboolean - is this field a private field or not?
0N/Aboolean - is this javac generated synthetic field or not?
0N/Aboolean - is this field a package private field or not?
0N/Aboolean - is this field a transient field or not?
0N/Aboolean - is this field final or not?
0N/Astring - name of this field
0N/Aboolean - is this field public or not?
0N/A<
h3>Initialization Script</
h3>
0N/Ajsdb engine looks for initialization script file named <
b>
jsdb.js</
b> in user's home directory. If found, it loads just after attaching to debuggee but before printing prompt for user's input. User can assume that
s/
he can access debuggee VM
0N/Astate during initialization script.
0N/A<
h3>Sample scripts</
h3>
0N/ASemantics and knowledge of application classes (for eg. AppServer's classes) would be needed to create app specific
0N/Ascripts. The following script samples are app-independent and provide a flavour of kind of scripts that can be written.
0N/A<
h4>Script to print system properties of JVM</
h4>
0N/A<
h4>Script to print JVM command line flags</
h4>
0N/A<
h4>Script to print class-wise histogram of objects</
h4>
0N/A// associate array to hold histogram
0N/A var classname = classof(obj).name;
0N/A if (histo[classname] == undefined) {
0N/A // first time we are visiting this class type
0N/A histo[classname] = 1;
0N/A// iterate through java heap calling 'func' for each object
0N/A// print the histogram
0N/A println('number of instances of ', i, ' = ', histo[i]);
0N/A<
h4>Script to print stack trace of all Java threads</
h4>
0N/Afunction printStackTrace(t) {
0N/A// walk through the list of threads and call printStackTrace
0N/A<
h4>Script to re-construct .class files for all non-bootstrap classes</
h4>
0N/A // not an array class and a non-bootstrap class
0N/A // create .class files in e:\tmp dir
0N/A dumpClass(cl, "e:\\tmp);
0N/A<
h4>Script to print paths of all
java.
io.
File's currently accessed</
h4>
0N/Afunction printFile(f) {
0N/A // print absolute path here
0N/A println(mirror(f).getAbsolutePath());
0N/A<
h3>Low level interface (VM State)</
h3>
0N/Ainterface</
a> provided by Rhino JavaScript engine.
0N/A<
h2>sapkg object</
h2>
0N/AThis object provides short names for SA package names. For eg. instead of writing
0N/AThis object contains all SA singleton objects such as VM, Universe, SymbolTable,
0N/ASystemDictionary, ObjectHeap, CollectedHeap, Debugger, CDebugger (if available),
0N/AInterpreter, TypeDataBase and Threads. For eg. to access SymbolTable of Java debuggee,
0N/Awe can use
sa.symbolTable. User can execute the following code to get fields of this object.
0N/A<
h4>Heap Iterators</
h4>
0N/A<
dt>forEachOop(callback)</
dt>
0N/A<
dd>calls a callback function for each Oop in Java heap</
dd>
0N/A<
dt>forEachOopOfKlass(callback, klass, [includeSubtypes])</
dt>
0N/A<
dd>calls a callback function for each Oop of a give Klass type
0N/AOptinally, third argument can specify whether to include subtype Oops
0N/A<
h4>System Dictionary Access</
h4>
0N/A<
dt>forEachKlass(callback)</
dt>
0N/A<
dd>calls a callback function for each Klass in Java heap</
dd>
0N/A<
dt>forEachKlassAndLoader(callback)</
dt>
0N/Acalls callback with Klass and initiating loader (Oop) for System dictionary
0N/A<
dt>forEachPrimArrayKlass(callback)</
dt>
0N/Acalls callback with Klass and initiating loader (Oop) for each
0N/Aprimitive array Klass in the system.
0N/A<
dt>findInstanceKlass(name)</
dt>
0N/Afinds the first instance klass with given name from System dictionary
0N/A<
h4>Thread, Frame Iterators</
h4>
0N/A<
dt>forEachJavaThread(callback)</
dt>
0N/A<
dd>calls callback for each Java Thread</
dd>
0N/A<
dt>forEachFrame(javaThread, callback)</
dt>
0N/A<
dd>calls callback for each Frame of a given JavaThread</
dd>
0N/A<
dt>forEachVFrame(javaThread, callback)</
dt>
0N/A<
dd>calls callback for each JavaVFrame of a given JavaThread</
dd>
0N/A<
dt>forEachThread(callback)</
dt>
0N/A<
dt>forEachCFrame(threadProxy, callback)</
dt>
0N/Acalls callback for each CFrame of a given ThreadProxy object
0N/A<
h4>Code blobs, Interpreter codelets</
h4>
0N/A<
dt>forEachCodeBlob(callback)</
dt>
0N/Acalls callback with each code blob in code cache
0N/A<
dt>findCodeBlob(address)</
dt>
0N/Afinds the code blob, if any, that contains the given address.
0N/AReturns null, on failure.
0N/A<
dt>findNMethod(address)</
dt>
0N/Afinds the NMethod that contains given address.
0N/A<
dt>pcDescAt(addr)</
dt>
0N/Areturns PCDesc at given address or null.
0N/A<
dt>forEachInterpCodelet(callbacl)</
dt>
0N/Acalls callback with each Interpreter codelet
0N/A<
h4>VM structs, constants</
h4>
0N/A<
dt>forEachType(callback)</
dt>
0N/Acalls callback for each Type in VM's type database
0N/A<
dt>forEachVMIntConst(callback)</
dt>
0N/Acalls callback for each named integer constant. passes name
0N/A<
dt>forEachVMLongConst(callback)</
dt>
0N/Acalls callback for each named long constant. passes name
0N/A<
dt>findVMType(name)</
dt>
0N/Afinds a VM type by name. returns null if no known Type of given name
0N/Aexists in type database.
0N/A<
dt>findVMIntConst(name)</
dt>
0N/Afinds an integer constant in type data base by name.
0N/A<
dt>findVMLongConst(name)</
dt>
0N/Afinds an long constant in type data base by name.
0N/A<
dt>vmTypeof(addr)</
dt>
0N/Areturns VM type of object at 'addr' if any. Else, returns null.
0N/A<
dt>isOfVMType(addr, type)</
dt>
0N/Areturns whether object at 'addr' is of VM type 'type' or not.
0N/A<
dt>printVMType(type, addr)</
dt>
0N/Aprints 'addr' as VM object of type 'type'
0N/A<
dt>print<
i>XXX</
i>(addr)</
dt>
0N/AFor each VM type, these functions are defined. For eg. there is printUniverse,
0N/AprintSystemDictionary etc. are available. Without 'addr' being passed static fields are printed. With 'addr' param being passed, instance fields are printed.
0N/A<
h4>Low level debugger facilities</
h4>
0N/A<
dt>num2addr(number)</
dt>
0N/Aconverts a (long) number to SA Address instance
0N/A<
dt>str2addr(string)</
dt>
0N/Aconverts a given hex string to SA Address instance
0N/A<
dt>any2addr(any)</
dt>
0N/ATakes a number or a string or an Address and returns
0N/Aan Address instance. For other types, returns 'undefined'
0N/A<
dt>addr2str(addr)</
dt>
0N/Aconverts a given Address instance to a hex string
0N/A<
dt>addr2num(addr)</
dt>
0N/Aconverts a given Address instance to a (long) number
0N/A<
dt>sym2addr(library, symbol)</
dt>
0N/Areturns Address of a given symbol in a given library (shared object or DLL)
0N/A<
dt>addr2sym(addr)</
dt>
0N/AReturns nearest symbol to a given address (if any). If no such symbol is found,
0N/Areturns the given address as a string.
0N/A<
dt>readBytesAt(addr, num)</
dt>
0N/Areturns 'num' bytes at 'addr' as a Java byte[]
0N/A<
dt>readWordsAt(addr, num)</
dt>
0N/Areturns 'num' words at 'addr' as a Java long[]
0N/A<
dt>readCStrAt(addr)</
dt>
0N/Areturns 'C' String at given address
0N/A<
dt>readCStrLen(addr)</
dt>
0N/Areturns the length of the 'C' String at given address
0N/A<
dt>readRegs(threadProxy)</
dt>
0N/Areturns register set (of Thread Context) of a given thread specified
0N/Aby threadProxy. return value is an associate array having name-value pairs
0N/A<
dt>regs(threadProxy)</
dt>
0N/Aprints register set of a given thread.
0N/A<
dt>mem(addr, [num])</
dt>
0N/Aprints 'num' words (address size) at 'addr'. Prints nearest symbol for address, if found.
0N/A<
dt>dis(addr, [num])</
dt>
0N/A<
dd>prints native code disassembly of 'num' bytes at given address 'addr'.
0N/ADefault value of 'num' is 4. This automatically detects whether the given address
0N/Ainside a nmethod. If so, it prints safepoint info, entry points , method signature etc.
0N/A<
dt>jdis(method [or addr])</
dt>
0N/Aprints Java bytecode disassembly for given method Oop or address of a method Oop.
0N/A<
dt>nmethoddis(nmethod)</
dt>
0N/Aprints disassembly of given nmethod object. Note that you don't have to call this directly
0N/Aprints Java stack trace for all Java threads
0N/A<
h4>Miscellaneous</
h4>
0N/A<
dt>addr2oop(addr)</
dt>
0N/Aconverts a given address to a Oop object
0N/A<
dt>oop2addr(oop)</
dt>
0N/Areturns address of a given Oop object
0N/A<
dt>isOfVMType(addr, type)</
dt>
0N/Areturns whether the given 'addr' points to a (C++) VM object of specified
0N/Atype. type may be specified by SA Type object or string name of the type.
0N/A<
dt>newVMObject(addr)</
dt>
0N/Areturns instance of SA object for a given address (similar to SA VirtualConstructor
0N/A<
dt>vmobj2addr(vmobject)</
dt>
0N/Areturns Address represented by a given SA VMObject
0N/A<
dt>addr2vmobj(addr)</
dt>
0N/A<
dd>same as newVMObject(addr)</
dd>
0N/A<
dt>whatis(addr)</
dt>
0N/Areturns string description of given address (using SA FindPointer and guess type API).
0N/Areturns whether a given address is a valid Oop address or not
0N/A<
h4>Moving b/w jsdb low level and high level interfaces</
h4>
0N/AJava objects of debuggee are represented by different script wrappers in high level
0N/Ainterface. In the low-level interface these are instances of SA Oop class or its'
0N/Asubclass. To move b/w low-level and high-level interfaces the following functions may
0N/A<
dt>oop2obj(oop)</
dt>
0N/Aconverts a given Oop object to a high-level wrapper object
0N/A<
dt>obj2oop(obj)</
dt>
0N/Aconverts a jsdb high level wrapper to underlying Oop instance
0N/A<
h3>JavaScript tips</
h3>
0N/A<
li>to know properties, functions of any object, use the script
0N/Afor(i in object) { println(i); }
0N/A<
li>to view the source code of any function, just type the name of
0N/Afunction in jsdb prompt
0N/A<
li>to view global functions, properties, run
0N/Afor(i in this) { println(i); }