Mon, 10 Jun 2013 11:30:51 +0200
8005849: JEP 167: Event-Based JVM Tracing
Reviewed-by: acorn, coleenp, sla
Contributed-by: Karen Kinnear <karen.kinnear@oracle.com>, Bengt Rutisson <bengt.rutisson@oracle.com>, Calvin Cheung <calvin.cheung@oracle.com>, Erik Gahlin <erik.gahlin@oracle.com>, Erik Helin <erik.helin@oracle.com>, Jesper Wilhelmsson <jesper.wilhelmsson@oracle.com>, Keith McGuigan <keith.mcguigan@oracle.com>, Mattias Tobiasson <mattias.tobiasson@oracle.com>, Markus Gronlund <markus.gronlund@oracle.com>, Mikael Auno <mikael.auno@oracle.com>, Nils Eliasson <nils.eliasson@oracle.com>, Nils Loodin <nils.loodin@oracle.com>, Rickard Backman <rickard.backman@oracle.com>, Staffan Larsen <staffan.larsen@oracle.com>, Stefan Karlsson <stefan.karlsson@oracle.com>, Yekaterina Kantserova <yekaterina.kantserova@oracle.com>
aoqi@0 | 1 | <html> |
aoqi@0 | 2 | <head> |
aoqi@0 | 3 | <title> |
aoqi@0 | 4 | JavaScript interface to Hotspot Serviceability Agent |
aoqi@0 | 5 | </title> |
aoqi@0 | 6 | </head> |
aoqi@0 | 7 | <body> |
aoqi@0 | 8 | <h1>JavaScript interface to Hotspot Serviceability Agent</h1> |
aoqi@0 | 9 | |
aoqi@0 | 10 | <p> |
aoqi@0 | 11 | Serviceability Agent (SA) provides Java API and tools to diagnose HotSpot Virtual Machine and |
aoqi@0 | 12 | Java apps running on it. SA is a snapshot debugger -- can be used to observe state of a frozen java process or java core dump. |
aoqi@0 | 13 | </p> |
aoqi@0 | 14 | |
aoqi@0 | 15 | <h2>Existing SA APIs</h2> |
aoqi@0 | 16 | <p> |
aoqi@0 | 17 | There are two application programmer interfaces (APIs) for SA: |
aoqi@0 | 18 | <dl> |
aoqi@0 | 19 | <dt>1. Private java API |
aoqi@0 | 20 | </dt> |
aoqi@0 | 21 | <dd> |
aoqi@0 | 22 | This tries to mimic hotspot VM's internal C++ classes and methods. Because VM data structures |
aoqi@0 | 23 | are a moving target, this API can never be 'stable'! Besides, to use SA's private API knowledge of |
aoqi@0 | 24 | HotSpot code base is essential. |
aoqi@0 | 25 | </dd> |
aoqi@0 | 26 | <dt>2. SA-JDI -- Java Debugger Interface read-only subset API |
aoqi@0 | 27 | </dt> |
aoqi@0 | 28 | <dd> |
aoqi@0 | 29 | This is read-only subset of JDI (Java Debugger Interface) |
aoqi@0 | 30 | This is a standardized interface to get java level state of a java process or java core dump. While this |
aoqi@0 | 31 | interface is useful, this misses parts of java level state from target process or core such as |
aoqi@0 | 32 | <ul> |
aoqi@0 | 33 | <li>heap walking interface -- only objects traceable to static variables (of classes) and local |
aoqi@0 | 34 | variables of stack frames can be accessed. |
aoqi@0 | 35 | <li>re-constructing .class from debuggee are missing. |
aoqi@0 | 36 | <li>re-constructing object mirrors for Java objects of the debuggee. |
aoqi@0 | 37 | </ul> |
aoqi@0 | 38 | </dd> |
aoqi@0 | 39 | </dl> |
aoqi@0 | 40 | </p> |
aoqi@0 | 41 | |
aoqi@0 | 42 | <h2>SA Scripting interface</h2> |
aoqi@0 | 43 | |
aoqi@0 | 44 | <p> |
aoqi@0 | 45 | Traditionally, platform debuggers such as dbx, gdb and Solaris mdb (Module Debugger), provide a scripting |
aoqi@0 | 46 | language interface. Scripting language interface provides easy-to-use, dynamically typed |
aoqi@0 | 47 | interface to access data structures from debuggee. dbx and mdb even allow user to write |
aoqi@0 | 48 | C/C++ modules to extend the scripting language commands. |
aoqi@0 | 49 | </p> |
aoqi@0 | 50 | |
aoqi@0 | 51 | <p> |
aoqi@0 | 52 | SA provides SOQL - Simple Object Query Language -- a SQL-like query language to access |
aoqi@0 | 53 | Java heap as an object database. SA's main GUI (HSDB) also exposes scripting interface of underlying debugger such as dbx, windbg. |
aoqi@0 | 54 | But to use this interface, user has to learn scripting interface of multiple debugger back-ends such as dbx, windbg. |
aoqi@0 | 55 | And these scripting interfaces are 'raw' in the sense that no java state is exposed -- only C/C++ state of VM is exposed. |
aoqi@0 | 56 | Higher level SA services are not available through scripting interface. |
aoqi@0 | 57 | </p> |
aoqi@0 | 58 | |
aoqi@0 | 59 | <p> |
aoqi@0 | 60 | <b>jsdb -- JavaScript Debugger</b> attempts to provide JavaScript interface to SA. |
aoqi@0 | 61 | jsdb provides |
aoqi@0 | 62 | |
aoqi@0 | 63 | <ul> |
aoqi@0 | 64 | <li>high-level hotspot (and SA) independent scripting interface |
aoqi@0 | 65 | <li>low-level SA-aware scripting interface. |
aoqi@0 | 66 | </ul> |
aoqi@0 | 67 | </p> |
aoqi@0 | 68 | |
aoqi@0 | 69 | <h2>High level interface (Java State)</h2> |
aoqi@0 | 70 | |
aoqi@0 | 71 | <b>jsdb</b> is a command line <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">JavaScript</a> shell based on |
aoqi@0 | 72 | <a href="http://www.mozilla.org/rhino/">Mozilla's Rhino JavaScript Engine</a>. |
aoqi@0 | 73 | This command line utility attaches to Java process or core file or remote debug server and waits for user input. |
aoqi@0 | 74 | This shell supports the following global functions and objects in addition to the standard JavaScript functions and |
aoqi@0 | 75 | objects: |
aoqi@0 | 76 | |
aoqi@0 | 77 | <h3>jdsb globals</h3> |
aoqi@0 | 78 | |
aoqi@0 | 79 | <table border="1"> |
aoqi@0 | 80 | <tr> |
aoqi@0 | 81 | <th>Function/Variable</th> |
aoqi@0 | 82 | <th>Description</th> |
aoqi@0 | 83 | </tr> |
aoqi@0 | 84 | <tr> |
aoqi@0 | 85 | <td> |
aoqi@0 | 86 | address(jobject) |
aoqi@0 | 87 | </td> |
aoqi@0 | 88 | <td> |
aoqi@0 | 89 | function that returns the address of the Java object as a string |
aoqi@0 | 90 | </td> |
aoqi@0 | 91 | </tr> |
aoqi@0 | 92 | <td> |
aoqi@0 | 93 | classof(jobject) |
aoqi@0 | 94 | </td> |
aoqi@0 | 95 | <td> |
aoqi@0 | 96 | function that returns the JavaScript object that represents class object of the Java object |
aoqi@0 | 97 | </td> |
aoqi@0 | 98 | </tr> |
aoqi@0 | 99 | <td> |
aoqi@0 | 100 | dumpClass(jclass,[dir]) |
aoqi@0 | 101 | </td> |
aoqi@0 | 102 | <td> |
aoqi@0 | 103 | function that writes .class for the given Java Class. Optionally (second arg) accepts the directory where the |
aoqi@0 | 104 | .class has to be written. |
aoqi@0 | 105 | </td> |
aoqi@0 | 106 | </tr> |
aoqi@0 | 107 | <td> |
aoqi@0 | 108 | help() |
aoqi@0 | 109 | </td> |
aoqi@0 | 110 | <td> |
aoqi@0 | 111 | function that prints help message for global functions and objects |
aoqi@0 | 112 | </td> |
aoqi@0 | 113 | </tr> |
aoqi@0 | 114 | <tr> |
aoqi@0 | 115 | <td> |
aoqi@0 | 116 | identityHash(jobject) |
aoqi@0 | 117 | </td> |
aoqi@0 | 118 | <td> |
aoqi@0 | 119 | function that returns the identity hashCode of the Java object |
aoqi@0 | 120 | </td> |
aoqi@0 | 121 | </tr> |
aoqi@0 | 122 | <tr> |
aoqi@0 | 123 | <td> |
aoqi@0 | 124 | mirror(jobject) |
aoqi@0 | 125 | </td> |
aoqi@0 | 126 | <td> |
aoqi@0 | 127 | function that returns a local mirror of the Java object. |
aoqi@0 | 128 | </td> |
aoqi@0 | 129 | </tr> |
aoqi@0 | 130 | <tr> |
aoqi@0 | 131 | <td> |
aoqi@0 | 132 | load([file1, file2,...]) |
aoqi@0 | 133 | </td> |
aoqi@0 | 134 | <td> |
aoqi@0 | 135 | function that loads zero or more JavaScript file(s). With no arguments, reads <stdin> for |
aoqi@0 | 136 | JavaScript code. |
aoqi@0 | 137 | </td> |
aoqi@0 | 138 | </tr> |
aoqi@0 | 139 | <tr> |
aoqi@0 | 140 | <td> |
aoqi@0 | 141 | object(string) |
aoqi@0 | 142 | </td> |
aoqi@0 | 143 | <td> |
aoqi@0 | 144 | function that converts a string address into Java object |
aoqi@0 | 145 | </td> |
aoqi@0 | 146 | </tr> |
aoqi@0 | 147 | <tr> |
aoqi@0 | 148 | <td> |
aoqi@0 | 149 | owner(jobject) |
aoqi@0 | 150 | </td> |
aoqi@0 | 151 | <td> |
aoqi@0 | 152 | function that returns the owner thread of this monitor or null |
aoqi@0 | 153 | </td> |
aoqi@0 | 154 | </tr> |
aoqi@0 | 155 | <tr> |
aoqi@0 | 156 | <td> |
aoqi@0 | 157 | sizeof(jobject) |
aoqi@0 | 158 | </td> |
aoqi@0 | 159 | <td> |
aoqi@0 | 160 | function that returns the size of Java object in bytes |
aoqi@0 | 161 | </td> |
aoqi@0 | 162 | </tr> |
aoqi@0 | 163 | <tr> |
aoqi@0 | 164 | <td> |
aoqi@0 | 165 | staticof(jclass, field) |
aoqi@0 | 166 | </td> |
aoqi@0 | 167 | <td> |
aoqi@0 | 168 | function that returns the value of given field of the given Java class |
aoqi@0 | 169 | </td> |
aoqi@0 | 170 | </tr> |
aoqi@0 | 171 | <tr> |
aoqi@0 | 172 | <td> |
aoqi@0 | 173 | print(expr1, expr2,...) |
aoqi@0 | 174 | </td> |
aoqi@0 | 175 | <td> |
aoqi@0 | 176 | function that prints zero or more JavaScript expressions after converting those as strings |
aoqi@0 | 177 | </td> |
aoqi@0 | 178 | </tr> |
aoqi@0 | 179 | <tr> |
aoqi@0 | 180 | <td> |
aoqi@0 | 181 | println(expr1, expr2..) |
aoqi@0 | 182 | </td> |
aoqi@0 | 183 | <td> |
aoqi@0 | 184 | function that same as print, but prints a newline at the end |
aoqi@0 | 185 | </td> |
aoqi@0 | 186 | </tr> |
aoqi@0 | 187 | <tr> |
aoqi@0 | 188 | <td> |
aoqi@0 | 189 | read([prompt]) |
aoqi@0 | 190 | </td> |
aoqi@0 | 191 | <td> |
aoqi@0 | 192 | function that reads a single line from standard input |
aoqi@0 | 193 | </td> |
aoqi@0 | 194 | </tr> |
aoqi@0 | 195 | <tr> |
aoqi@0 | 196 | <td> |
aoqi@0 | 197 | quit() |
aoqi@0 | 198 | </td> |
aoqi@0 | 199 | <td> |
aoqi@0 | 200 | function that quits the interactive load call as well as the shell |
aoqi@0 | 201 | </td> |
aoqi@0 | 202 | </tr> |
aoqi@0 | 203 | <tr> |
aoqi@0 | 204 | <td> |
aoqi@0 | 205 | jvm |
aoqi@0 | 206 | </td> |
aoqi@0 | 207 | <td> |
aoqi@0 | 208 | variable -- a JavaScript object that represents the target jvm that is being debugged |
aoqi@0 | 209 | </td> |
aoqi@0 | 210 | </tr> |
aoqi@0 | 211 | </table> |
aoqi@0 | 212 | |
aoqi@0 | 213 | <h3>jvm object</h3> |
aoqi@0 | 214 | |
aoqi@0 | 215 | <p> |
aoqi@0 | 216 | jvm object supports the following read-only properties. |
aoqi@0 | 217 | </p> |
aoqi@0 | 218 | |
aoqi@0 | 219 | <table border="1"> |
aoqi@0 | 220 | <tr> |
aoqi@0 | 221 | <th> |
aoqi@0 | 222 | Property name |
aoqi@0 | 223 | </th> |
aoqi@0 | 224 | <th> |
aoqi@0 | 225 | Description |
aoqi@0 | 226 | </th> |
aoqi@0 | 227 | </tr> |
aoqi@0 | 228 | <tr> |
aoqi@0 | 229 | <td> |
aoqi@0 | 230 | threads |
aoqi@0 | 231 | </td> |
aoqi@0 | 232 | <td> |
aoqi@0 | 233 | array of Java threads from the debuggee |
aoqi@0 | 234 | </td> |
aoqi@0 | 235 | </tr> |
aoqi@0 | 236 | <tr> |
aoqi@0 | 237 | <td> |
aoqi@0 | 238 | heap |
aoqi@0 | 239 | </td> |
aoqi@0 | 240 | <td> |
aoqi@0 | 241 | object representing the heap of the debuggee |
aoqi@0 | 242 | </td> |
aoqi@0 | 243 | </tr> |
aoqi@0 | 244 | <tr> |
aoqi@0 | 245 | <td> |
aoqi@0 | 246 | type |
aoqi@0 | 247 | </td> |
aoqi@0 | 248 | <td> |
aoqi@0 | 249 | string value that is either "Server" or "Client" or "Core" -- the flavour of debuggee VM |
aoqi@0 | 250 | </td> |
aoqi@0 | 251 | </tr> |
aoqi@0 | 252 | <tr> |
aoqi@0 | 253 | <td> |
aoqi@0 | 254 | bootClassPath |
aoqi@0 | 255 | </td> |
aoqi@0 | 256 | <td> |
aoqi@0 | 257 | string value of bootclasspath of the debuggee |
aoqi@0 | 258 | </td> |
aoqi@0 | 259 | </tr> |
aoqi@0 | 260 | <tr> |
aoqi@0 | 261 | <td> |
aoqi@0 | 262 | cpu |
aoqi@0 | 263 | </td> |
aoqi@0 | 264 | <td> |
aoqi@0 | 265 | string value of cpu on which the debuggee runs/ran |
aoqi@0 | 266 | </td> |
aoqi@0 | 267 | </tr> |
aoqi@0 | 268 | <tr> |
aoqi@0 | 269 | <td> |
aoqi@0 | 270 | sysProps |
aoqi@0 | 271 | </td> |
aoqi@0 | 272 | <td> |
aoqi@0 | 273 | name-value pairs (JavaScript associative array) of Java System properties of the debuggee |
aoqi@0 | 274 | </td> |
aoqi@0 | 275 | </tr> |
aoqi@0 | 276 | <tr> |
aoqi@0 | 277 | <td> |
aoqi@0 | 278 | addressSize |
aoqi@0 | 279 | </td> |
aoqi@0 | 280 | <td> |
aoqi@0 | 281 | int value -- 32 for 32 bit debuggee, 64 for 64 bit debuggee |
aoqi@0 | 282 | </td> |
aoqi@0 | 283 | </tr> |
aoqi@0 | 284 | <tr> |
aoqi@0 | 285 | <td> |
aoqi@0 | 286 | os |
aoqi@0 | 287 | </td> |
aoqi@0 | 288 | <td> |
aoqi@0 | 289 | string value of OS on which the debuggee runs/ran |
aoqi@0 | 290 | </td> |
aoqi@0 | 291 | </tr> |
aoqi@0 | 292 | <tr> |
aoqi@0 | 293 | <td> |
aoqi@0 | 294 | buildInfo |
aoqi@0 | 295 | </td> |
aoqi@0 | 296 | <td> |
aoqi@0 | 297 | internal build info string from debuggee |
aoqi@0 | 298 | </td> |
aoqi@0 | 299 | </tr> |
aoqi@0 | 300 | <tr> |
aoqi@0 | 301 | <td> |
aoqi@0 | 302 | flags |
aoqi@0 | 303 | </td> |
aoqi@0 | 304 | <td> |
aoqi@0 | 305 | name-value pairs (JavaScript associative array) of JVM command line flags of the debuggee |
aoqi@0 | 306 | </td> |
aoqi@0 | 307 | </tr> |
aoqi@0 | 308 | <tr> |
aoqi@0 | 309 | <td> |
aoqi@0 | 310 | classPath |
aoqi@0 | 311 | </td> |
aoqi@0 | 312 | <td> |
aoqi@0 | 313 | string value of classpath of the debuggee |
aoqi@0 | 314 | </td> |
aoqi@0 | 315 | </tr> |
aoqi@0 | 316 | <tr> |
aoqi@0 | 317 | <td> |
aoqi@0 | 318 | userDir |
aoqi@0 | 319 | </td> |
aoqi@0 | 320 | <td> |
aoqi@0 | 321 | string value of user.dir System property of the debuggee |
aoqi@0 | 322 | </td> |
aoqi@0 | 323 | </tr> |
aoqi@0 | 324 | </table> |
aoqi@0 | 325 | |
aoqi@0 | 326 | <h3>heap object</h3> |
aoqi@0 | 327 | |
aoqi@0 | 328 | <p> |
aoqi@0 | 329 | heap object represents Java heap of the debuggee VM |
aoqi@0 | 330 | </p> |
aoqi@0 | 331 | <table border="1"> |
aoqi@0 | 332 | <tr> |
aoqi@0 | 333 | <th> |
aoqi@0 | 334 | Function or property name |
aoqi@0 | 335 | </th> |
aoqi@0 | 336 | <th> |
aoqi@0 | 337 | Description |
aoqi@0 | 338 | </th> |
aoqi@0 | 339 | </tr> |
aoqi@0 | 340 | <tr> |
aoqi@0 | 341 | <td> |
aoqi@0 | 342 | capacity |
aoqi@0 | 343 | </td> |
aoqi@0 | 344 | <td> |
aoqi@0 | 345 | byte size of capacity of the heap |
aoqi@0 | 346 | </td> |
aoqi@0 | 347 | </tr> |
aoqi@0 | 348 | <tr> |
aoqi@0 | 349 | <td> |
aoqi@0 | 350 | used |
aoqi@0 | 351 | </td> |
aoqi@0 | 352 | <td> |
aoqi@0 | 353 | byte size of used portion (of live objects) of the heap |
aoqi@0 | 354 | </td> |
aoqi@0 | 355 | </tr> |
aoqi@0 | 356 | <tr> |
aoqi@0 | 357 | <td> |
aoqi@0 | 358 | forEachObject(func, [class], [include subtypes -- true|false]) |
aoqi@0 | 359 | </td> |
aoqi@0 | 360 | <td> |
aoqi@0 | 361 | This function accepts a callback function 'func' and optionally class name and boolean arguments. |
aoqi@0 | 362 | This function calls the callback for each Java object in the debuggee's heap. The optional class |
aoqi@0 | 363 | argument may be used to receive objects of given class only. The third arguments specifies whether |
aoqi@0 | 364 | to include objects of subtype of given class [or interface] or not. The default value of class is "java.lang.Object" |
aoqi@0 | 365 | and and that of the third argument is true. i.e., by default all objects are included. |
aoqi@0 | 366 | </td> |
aoqi@0 | 367 | </tr> |
aoqi@0 | 368 | <tr> |
aoqi@0 | 369 | <td> |
aoqi@0 | 370 | forEachClass(func, [initiating loader -- true|false]) |
aoqi@0 | 371 | </td> |
aoqi@0 | 372 | <td> |
aoqi@0 | 373 | This function accepts a callback function 'func'. This function iterates through the classes of the debuggee and calls the |
aoqi@0 | 374 | callback for each class. The second parameter tells whether to pass initiating loader to the iterator callback or not. |
aoqi@0 | 375 | </td> |
aoqi@0 | 376 | </tr> |
aoqi@0 | 377 | </table> |
aoqi@0 | 378 | |
aoqi@0 | 379 | <h3>Accessing Java objects and arrays in script</h3> |
aoqi@0 | 380 | |
aoqi@0 | 381 | <p> |
aoqi@0 | 382 | From a given Java object, we can access all fields of the Java object by usual '.' operator. i.e., if you got a Java object |
aoqi@0 | 383 | called 'o' of type java.lang.Thread from debuggee, you can access 'stackSize' field by o.stackSize syntax. Similarly, length of Java array |
aoqi@0 | 384 | objects can be accessed by length property. And array indexing follows usual syntax. i.e., n'th element of array 'a' is |
aoqi@0 | 385 | accessed by a[n]. |
aoqi@0 | 386 | </p> |
aoqi@0 | 387 | |
aoqi@0 | 388 | <h3>jvm.threads array</h3> |
aoqi@0 | 389 | |
aoqi@0 | 390 | <p> |
aoqi@0 | 391 | This is a JavaScript array of Java threads of the debuggee. As usual, 'length' property tells the number of threads and individual |
aoqi@0 | 392 | threads may be accessed by index operator -- i.e, jvm.threads[0] returns the first thread. |
aoqi@0 | 393 | </p> |
aoqi@0 | 394 | |
aoqi@0 | 395 | <h3>thread object</h3> |
aoqi@0 | 396 | |
aoqi@0 | 397 | |
aoqi@0 | 398 | <p> |
aoqi@0 | 399 | In addition to the fields of java.lang.Thread (or subclass) fields, thread objects have two additional properties. |
aoqi@0 | 400 | |
aoqi@0 | 401 | <ul> |
aoqi@0 | 402 | <li>frames -- array of stack frame objects |
aoqi@0 | 403 | <li>monitors -- array of monitor objects owned by the thread |
aoqi@0 | 404 | </ul> |
aoqi@0 | 405 | |
aoqi@0 | 406 | </p> |
aoqi@0 | 407 | |
aoqi@0 | 408 | <h3>stack frame object</h3> |
aoqi@0 | 409 | |
aoqi@0 | 410 | <table border="1"> |
aoqi@0 | 411 | <tr> |
aoqi@0 | 412 | <th> |
aoqi@0 | 413 | Property name |
aoqi@0 | 414 | </th> |
aoqi@0 | 415 | <th> |
aoqi@0 | 416 | Description |
aoqi@0 | 417 | </th> |
aoqi@0 | 418 | </tr> |
aoqi@0 | 419 | <td> |
aoqi@0 | 420 | thisObject |
aoqi@0 | 421 | </td> |
aoqi@0 | 422 | <td> |
aoqi@0 | 423 | Object representing 'this' of the current frame [will be null for static methods] |
aoqi@0 | 424 | </td> |
aoqi@0 | 425 | </tr> |
aoqi@0 | 426 | <tr> |
aoqi@0 | 427 | <td> |
aoqi@0 | 428 | locals |
aoqi@0 | 429 | </td> |
aoqi@0 | 430 | <td> |
aoqi@0 | 431 | name-value pairs of local variables [JavaScript associative array] |
aoqi@0 | 432 | </td> |
aoqi@0 | 433 | </tr> |
aoqi@0 | 434 | <tr> |
aoqi@0 | 435 | <td> |
aoqi@0 | 436 | line |
aoqi@0 | 437 | </td> |
aoqi@0 | 438 | <td> |
aoqi@0 | 439 | Java source line number at which the frame is executing |
aoqi@0 | 440 | </td> |
aoqi@0 | 441 | </tr> |
aoqi@0 | 442 | <tr> |
aoqi@0 | 443 | <td> |
aoqi@0 | 444 | bci |
aoqi@0 | 445 | </td> |
aoqi@0 | 446 | <td> |
aoqi@0 | 447 | byte code index of the bytecode that the frame is executing |
aoqi@0 | 448 | </td> |
aoqi@0 | 449 | </tr> |
aoqi@0 | 450 | <tr> |
aoqi@0 | 451 | <td> |
aoqi@0 | 452 | thread |
aoqi@0 | 453 | </td> |
aoqi@0 | 454 | <td> |
aoqi@0 | 455 | thread to which this frame belongs |
aoqi@0 | 456 | </td> |
aoqi@0 | 457 | </tr> |
aoqi@0 | 458 | <tr> |
aoqi@0 | 459 | <td> |
aoqi@0 | 460 | method |
aoqi@0 | 461 | </td> |
aoqi@0 | 462 | <td> |
aoqi@0 | 463 | Java method that the frame is executing |
aoqi@0 | 464 | </td> |
aoqi@0 | 465 | </tr> |
aoqi@0 | 466 | </table> |
aoqi@0 | 467 | |
aoqi@0 | 468 | <h3>method object</h3> |
aoqi@0 | 469 | |
aoqi@0 | 470 | <p> |
aoqi@0 | 471 | method object represents a Java method of debuggee |
aoqi@0 | 472 | </p> |
aoqi@0 | 473 | |
aoqi@0 | 474 | <table border="1"> |
aoqi@0 | 475 | <tr> |
aoqi@0 | 476 | <th> |
aoqi@0 | 477 | Property name |
aoqi@0 | 478 | </th> |
aoqi@0 | 479 | <th> |
aoqi@0 | 480 | Description |
aoqi@0 | 481 | </th> |
aoqi@0 | 482 | </tr> |
aoqi@0 | 483 | <tr> |
aoqi@0 | 484 | <td> |
aoqi@0 | 485 | isStatic |
aoqi@0 | 486 | </td> |
aoqi@0 | 487 | <td> |
aoqi@0 | 488 | boolean - true for static methods and false for non-static methods |
aoqi@0 | 489 | </td> |
aoqi@0 | 490 | </tr> |
aoqi@0 | 491 | |
aoqi@0 | 492 | <tr> |
aoqi@0 | 493 | <td> |
aoqi@0 | 494 | isSynchronized |
aoqi@0 | 495 | </td> |
aoqi@0 | 496 | <td> |
aoqi@0 | 497 | boolean - true for synchronized methods and false for non-synchronized methods |
aoqi@0 | 498 | </td> |
aoqi@0 | 499 | </tr> |
aoqi@0 | 500 | |
aoqi@0 | 501 | <tr> |
aoqi@0 | 502 | <td> |
aoqi@0 | 503 | isNative |
aoqi@0 | 504 | </td> |
aoqi@0 | 505 | <td> |
aoqi@0 | 506 | boolean - true for native methods and false for non-native methods |
aoqi@0 | 507 | </td> |
aoqi@0 | 508 | </tr> |
aoqi@0 | 509 | |
aoqi@0 | 510 | <tr> |
aoqi@0 | 511 | <td> |
aoqi@0 | 512 | isProtected |
aoqi@0 | 513 | </td> |
aoqi@0 | 514 | <td> |
aoqi@0 | 515 | boolean - true for protected methods and false for non-protected methods |
aoqi@0 | 516 | </td> |
aoqi@0 | 517 | </tr> |
aoqi@0 | 518 | |
aoqi@0 | 519 | <tr> |
aoqi@0 | 520 | <td> |
aoqi@0 | 521 | isPrivate |
aoqi@0 | 522 | </td> |
aoqi@0 | 523 | <td> |
aoqi@0 | 524 | boolean - true for private methods and false for non-private methods |
aoqi@0 | 525 | </td> |
aoqi@0 | 526 | </tr> |
aoqi@0 | 527 | |
aoqi@0 | 528 | <tr> |
aoqi@0 | 529 | <td> |
aoqi@0 | 530 | isSynthetic |
aoqi@0 | 531 | </td> |
aoqi@0 | 532 | <td> |
aoqi@0 | 533 | boolean - true for Javac generated synthetic methods and false for non-synthetic methods |
aoqi@0 | 534 | </td> |
aoqi@0 | 535 | </tr> |
aoqi@0 | 536 | |
aoqi@0 | 537 | <tr> |
aoqi@0 | 538 | <td> |
aoqi@0 | 539 | isPackagePrivate |
aoqi@0 | 540 | </td> |
aoqi@0 | 541 | <td> |
aoqi@0 | 542 | boolean - true for package-private methods and false for non-package-private methods |
aoqi@0 | 543 | </td> |
aoqi@0 | 544 | </tr> |
aoqi@0 | 545 | |
aoqi@0 | 546 | <tr> |
aoqi@0 | 547 | <td> |
aoqi@0 | 548 | isPublic |
aoqi@0 | 549 | </td> |
aoqi@0 | 550 | <td> |
aoqi@0 | 551 | boolean - true for public methods and false for non-public methods |
aoqi@0 | 552 | </td> |
aoqi@0 | 553 | </tr> |
aoqi@0 | 554 | |
aoqi@0 | 555 | <tr> |
aoqi@0 | 556 | <td> |
aoqi@0 | 557 | holder |
aoqi@0 | 558 | </td> |
aoqi@0 | 559 | <td> |
aoqi@0 | 560 | an object that represents Class that contains this method |
aoqi@0 | 561 | </td> |
aoqi@0 | 562 | </tr> |
aoqi@0 | 563 | |
aoqi@0 | 564 | <tr> |
aoqi@0 | 565 | <td> |
aoqi@0 | 566 | signature |
aoqi@0 | 567 | </td> |
aoqi@0 | 568 | <td> |
aoqi@0 | 569 | string -- signature of this method |
aoqi@0 | 570 | </td> |
aoqi@0 | 571 | </tr> |
aoqi@0 | 572 | |
aoqi@0 | 573 | <tr> |
aoqi@0 | 574 | <td> |
aoqi@0 | 575 | isObsolete |
aoqi@0 | 576 | </td> |
aoqi@0 | 577 | <td> |
aoqi@0 | 578 | boolean - true for obsolete (hotswapped) methods and false for non-obsolete methods |
aoqi@0 | 579 | </td> |
aoqi@0 | 580 | </tr> |
aoqi@0 | 581 | |
aoqi@0 | 582 | <tr> |
aoqi@0 | 583 | <td> |
aoqi@0 | 584 | isStrict |
aoqi@0 | 585 | </td> |
aoqi@0 | 586 | <td> |
aoqi@0 | 587 | boolean - true for strictfp methods and false for non-strictfp methods |
aoqi@0 | 588 | </td> |
aoqi@0 | 589 | </tr> |
aoqi@0 | 590 | |
aoqi@0 | 591 | <tr> |
aoqi@0 | 592 | <td> |
aoqi@0 | 593 | isFinal |
aoqi@0 | 594 | </td> |
aoqi@0 | 595 | <td> |
aoqi@0 | 596 | boolean - true for final methods and false for non-final methods |
aoqi@0 | 597 | </td> |
aoqi@0 | 598 | </tr> |
aoqi@0 | 599 | |
aoqi@0 | 600 | <tr> |
aoqi@0 | 601 | <td> |
aoqi@0 | 602 | name |
aoqi@0 | 603 | </td> |
aoqi@0 | 604 | <td> |
aoqi@0 | 605 | string - name of this method |
aoqi@0 | 606 | </td> |
aoqi@0 | 607 | </tr> |
aoqi@0 | 608 | </table> |
aoqi@0 | 609 | |
aoqi@0 | 610 | <h3>class object</h3> |
aoqi@0 | 611 | |
aoqi@0 | 612 | <p> |
aoqi@0 | 613 | A class object represents loaded Java class in debuggee VM. This represents java.lang.Class instance in the debuggee. |
aoqi@0 | 614 | This is type of return value of classof global function. Also, method.holder property and field.holder are |
aoqi@0 | 615 | of this type. |
aoqi@0 | 616 | </p> |
aoqi@0 | 617 | |
aoqi@0 | 618 | <table border="1"> |
aoqi@0 | 619 | <tr> |
aoqi@0 | 620 | <th> |
aoqi@0 | 621 | Property name |
aoqi@0 | 622 | </th> |
aoqi@0 | 623 | <th> |
aoqi@0 | 624 | Description |
aoqi@0 | 625 | </th> |
aoqi@0 | 626 | </tr> |
aoqi@0 | 627 | |
aoqi@0 | 628 | <tr> |
aoqi@0 | 629 | <td> |
aoqi@0 | 630 | name |
aoqi@0 | 631 | </td> |
aoqi@0 | 632 | <td> |
aoqi@0 | 633 | name of this class |
aoqi@0 | 634 | </td> |
aoqi@0 | 635 | </tr> |
aoqi@0 | 636 | |
aoqi@0 | 637 | <tr> |
aoqi@0 | 638 | <td> |
aoqi@0 | 639 | superClass |
aoqi@0 | 640 | </td> |
aoqi@0 | 641 | <td> |
aoqi@0 | 642 | class object representing super class of this class |
aoqi@0 | 643 | </td> |
aoqi@0 | 644 | </tr> |
aoqi@0 | 645 | |
aoqi@0 | 646 | <tr> |
aoqi@0 | 647 | <td> |
aoqi@0 | 648 | isArrayClass |
aoqi@0 | 649 | </td> |
aoqi@0 | 650 | <td> |
aoqi@0 | 651 | boolean -- is the current class an array class? |
aoqi@0 | 652 | </td> |
aoqi@0 | 653 | </tr> |
aoqi@0 | 654 | |
aoqi@0 | 655 | <tr> |
aoqi@0 | 656 | <td> |
aoqi@0 | 657 | isStatic |
aoqi@0 | 658 | </td> |
aoqi@0 | 659 | <td> |
aoqi@0 | 660 | boolean -- is the current class static or not |
aoqi@0 | 661 | </td> |
aoqi@0 | 662 | </tr> |
aoqi@0 | 663 | |
aoqi@0 | 664 | <tr> |
aoqi@0 | 665 | <td> |
aoqi@0 | 666 | isInterface |
aoqi@0 | 667 | </td> |
aoqi@0 | 668 | <td> |
aoqi@0 | 669 | boolean -- is the current class an interface |
aoqi@0 | 670 | </td> |
aoqi@0 | 671 | </tr> |
aoqi@0 | 672 | |
aoqi@0 | 673 | <tr> |
aoqi@0 | 674 | <td> |
aoqi@0 | 675 | isAbstract |
aoqi@0 | 676 | </td> |
aoqi@0 | 677 | <td> |
aoqi@0 | 678 | boolean -- is the current class abstract or not |
aoqi@0 | 679 | </td> |
aoqi@0 | 680 | </tr> |
aoqi@0 | 681 | |
aoqi@0 | 682 | <tr> |
aoqi@0 | 683 | <td> |
aoqi@0 | 684 | isProtected |
aoqi@0 | 685 | </td> |
aoqi@0 | 686 | <td> |
aoqi@0 | 687 | boolean -- is the current class protected or not |
aoqi@0 | 688 | </td> |
aoqi@0 | 689 | </tr> |
aoqi@0 | 690 | |
aoqi@0 | 691 | <tr> |
aoqi@0 | 692 | <td> |
aoqi@0 | 693 | isPrivate |
aoqi@0 | 694 | </td> |
aoqi@0 | 695 | <td> |
aoqi@0 | 696 | boolean -- is the current class private or not |
aoqi@0 | 697 | </td> |
aoqi@0 | 698 | </tr> |
aoqi@0 | 699 | |
aoqi@0 | 700 | <tr> |
aoqi@0 | 701 | <td> |
aoqi@0 | 702 | isPackagePrivate |
aoqi@0 | 703 | </td> |
aoqi@0 | 704 | <td> |
aoqi@0 | 705 | boolean -- is the current class package private or not |
aoqi@0 | 706 | </td> |
aoqi@0 | 707 | </tr> |
aoqi@0 | 708 | |
aoqi@0 | 709 | <tr> |
aoqi@0 | 710 | <td> |
aoqi@0 | 711 | isSynthetic |
aoqi@0 | 712 | </td> |
aoqi@0 | 713 | <td> |
aoqi@0 | 714 | boolean -- is the current class synthetic or not |
aoqi@0 | 715 | </td> |
aoqi@0 | 716 | </tr> |
aoqi@0 | 717 | |
aoqi@0 | 718 | <tr> |
aoqi@0 | 719 | <td> |
aoqi@0 | 720 | classLoader |
aoqi@0 | 721 | </td> |
aoqi@0 | 722 | <td> |
aoqi@0 | 723 | object that represents ClassLoader object that loaded the current class |
aoqi@0 | 724 | </td> |
aoqi@0 | 725 | </tr> |
aoqi@0 | 726 | |
aoqi@0 | 727 | |
aoqi@0 | 728 | <tr> |
aoqi@0 | 729 | <td> |
aoqi@0 | 730 | fields |
aoqi@0 | 731 | </td> |
aoqi@0 | 732 | <td> |
aoqi@0 | 733 | array of static and instance fields of the current class |
aoqi@0 | 734 | </td> |
aoqi@0 | 735 | </tr> |
aoqi@0 | 736 | |
aoqi@0 | 737 | <tr> |
aoqi@0 | 738 | <td> |
aoqi@0 | 739 | protectionDomain |
aoqi@0 | 740 | </td> |
aoqi@0 | 741 | <td> |
aoqi@0 | 742 | protection domain to which current class belongs |
aoqi@0 | 743 | </td> |
aoqi@0 | 744 | </tr> |
aoqi@0 | 745 | |
aoqi@0 | 746 | <tr> |
aoqi@0 | 747 | <td> |
aoqi@0 | 748 | isPublic |
aoqi@0 | 749 | </td> |
aoqi@0 | 750 | <td> |
aoqi@0 | 751 | boolean -- is the current class public or not |
aoqi@0 | 752 | </td> |
aoqi@0 | 753 | </tr> |
aoqi@0 | 754 | |
aoqi@0 | 755 | <tr> |
aoqi@0 | 756 | <td> |
aoqi@0 | 757 | signers |
aoqi@0 | 758 | </td> |
aoqi@0 | 759 | <td> |
aoqi@0 | 760 | array of signers for current class |
aoqi@0 | 761 | </td> |
aoqi@0 | 762 | </tr> |
aoqi@0 | 763 | |
aoqi@0 | 764 | <tr> |
aoqi@0 | 765 | <td> |
aoqi@0 | 766 | sourceFile |
aoqi@0 | 767 | </td> |
aoqi@0 | 768 | <td> |
aoqi@0 | 769 | string -- name of the source file for current class |
aoqi@0 | 770 | </td> |
aoqi@0 | 771 | </tr> |
aoqi@0 | 772 | |
aoqi@0 | 773 | <tr> |
aoqi@0 | 774 | <td> |
aoqi@0 | 775 | interfaces |
aoqi@0 | 776 | </td> |
aoqi@0 | 777 | <td> |
aoqi@0 | 778 | array -- interfaces implemented by current class |
aoqi@0 | 779 | </td> |
aoqi@0 | 780 | </tr> |
aoqi@0 | 781 | |
aoqi@0 | 782 | <tr> |
aoqi@0 | 783 | <td> |
aoqi@0 | 784 | isStrict |
aoqi@0 | 785 | </td> |
aoqi@0 | 786 | <td> |
aoqi@0 | 787 | boolean -- is the current class strictfp or not |
aoqi@0 | 788 | </td> |
aoqi@0 | 789 | </tr> |
aoqi@0 | 790 | |
aoqi@0 | 791 | <tr> |
aoqi@0 | 792 | <td> |
aoqi@0 | 793 | methods |
aoqi@0 | 794 | </td> |
aoqi@0 | 795 | <td> |
aoqi@0 | 796 | array of methods (static and instance) of the current class |
aoqi@0 | 797 | </td> |
aoqi@0 | 798 | </tr> |
aoqi@0 | 799 | |
aoqi@0 | 800 | |
aoqi@0 | 801 | <tr> |
aoqi@0 | 802 | <td> |
aoqi@0 | 803 | isFinal |
aoqi@0 | 804 | </td> |
aoqi@0 | 805 | <td> |
aoqi@0 | 806 | boolean -- is the current class final or not |
aoqi@0 | 807 | </td> |
aoqi@0 | 808 | </tr> |
aoqi@0 | 809 | |
aoqi@0 | 810 | <tr> |
aoqi@0 | 811 | <td> |
aoqi@0 | 812 | statics |
aoqi@0 | 813 | </td> |
aoqi@0 | 814 | <td> |
aoqi@0 | 815 | name-value pairs (JavaScript associate array) of static fields of the current class |
aoqi@0 | 816 | </td> |
aoqi@0 | 817 | </tr> |
aoqi@0 | 818 | </table> |
aoqi@0 | 819 | |
aoqi@0 | 820 | <h3>field object</h3> |
aoqi@0 | 821 | <p> |
aoqi@0 | 822 | field represents a static or instance field of some class in debuggee |
aoqi@0 | 823 | </p> |
aoqi@0 | 824 | |
aoqi@0 | 825 | <table border="1"> |
aoqi@0 | 826 | <tr> |
aoqi@0 | 827 | <th> |
aoqi@0 | 828 | Property name |
aoqi@0 | 829 | </th> |
aoqi@0 | 830 | <th> |
aoqi@0 | 831 | Description |
aoqi@0 | 832 | </th> |
aoqi@0 | 833 | </tr> |
aoqi@0 | 834 | |
aoqi@0 | 835 | <tr> |
aoqi@0 | 836 | <td> |
aoqi@0 | 837 | isStatic |
aoqi@0 | 838 | </td> |
aoqi@0 | 839 | <td> |
aoqi@0 | 840 | boolean -- is this field a static field? |
aoqi@0 | 841 | </td> |
aoqi@0 | 842 | </tr> |
aoqi@0 | 843 | |
aoqi@0 | 844 | <tr> |
aoqi@0 | 845 | <td> |
aoqi@0 | 846 | holder |
aoqi@0 | 847 | </td> |
aoqi@0 | 848 | <td> |
aoqi@0 | 849 | class that owns this field |
aoqi@0 | 850 | </td> |
aoqi@0 | 851 | </tr> |
aoqi@0 | 852 | |
aoqi@0 | 853 | <tr> |
aoqi@0 | 854 | <td> |
aoqi@0 | 855 | signature |
aoqi@0 | 856 | </td> |
aoqi@0 | 857 | <td> |
aoqi@0 | 858 | string signature of this field |
aoqi@0 | 859 | </td> |
aoqi@0 | 860 | </tr> |
aoqi@0 | 861 | |
aoqi@0 | 862 | <tr> |
aoqi@0 | 863 | <td> |
aoqi@0 | 864 | isProtected |
aoqi@0 | 865 | </td> |
aoqi@0 | 866 | <td> |
aoqi@0 | 867 | boolean - is this field a protected field or not? |
aoqi@0 | 868 | </td> |
aoqi@0 | 869 | </tr> |
aoqi@0 | 870 | |
aoqi@0 | 871 | <tr> |
aoqi@0 | 872 | <td> |
aoqi@0 | 873 | isPrivate |
aoqi@0 | 874 | </td> |
aoqi@0 | 875 | <td> |
aoqi@0 | 876 | boolean - is this field a private field or not? |
aoqi@0 | 877 | </td> |
aoqi@0 | 878 | </tr> |
aoqi@0 | 879 | |
aoqi@0 | 880 | <tr> |
aoqi@0 | 881 | <td> |
aoqi@0 | 882 | isSynthetic |
aoqi@0 | 883 | </td> |
aoqi@0 | 884 | <td> |
aoqi@0 | 885 | boolean - is this javac generated synthetic field or not? |
aoqi@0 | 886 | </td> |
aoqi@0 | 887 | </tr> |
aoqi@0 | 888 | |
aoqi@0 | 889 | <tr> |
aoqi@0 | 890 | <td> |
aoqi@0 | 891 | isPackagePrivate |
aoqi@0 | 892 | </td> |
aoqi@0 | 893 | <td> |
aoqi@0 | 894 | boolean - is this field a package private field or not? |
aoqi@0 | 895 | </td> |
aoqi@0 | 896 | </tr> |
aoqi@0 | 897 | |
aoqi@0 | 898 | <tr> |
aoqi@0 | 899 | <td> |
aoqi@0 | 900 | isTransient |
aoqi@0 | 901 | </td> |
aoqi@0 | 902 | <td> |
aoqi@0 | 903 | boolean - is this field a transient field or not? |
aoqi@0 | 904 | </td> |
aoqi@0 | 905 | </tr> |
aoqi@0 | 906 | |
aoqi@0 | 907 | <tr> |
aoqi@0 | 908 | <td> |
aoqi@0 | 909 | isFinal |
aoqi@0 | 910 | </td> |
aoqi@0 | 911 | <td> |
aoqi@0 | 912 | boolean - is this field final or not? |
aoqi@0 | 913 | </td> |
aoqi@0 | 914 | </tr> |
aoqi@0 | 915 | |
aoqi@0 | 916 | <tr> |
aoqi@0 | 917 | <td> |
aoqi@0 | 918 | name |
aoqi@0 | 919 | </td> |
aoqi@0 | 920 | <td> |
aoqi@0 | 921 | string - name of this field |
aoqi@0 | 922 | </td> |
aoqi@0 | 923 | </tr> |
aoqi@0 | 924 | |
aoqi@0 | 925 | <tr> |
aoqi@0 | 926 | <td> |
aoqi@0 | 927 | isPublic |
aoqi@0 | 928 | </td> |
aoqi@0 | 929 | <td> |
aoqi@0 | 930 | boolean - is this field public or not? |
aoqi@0 | 931 | </td> |
aoqi@0 | 932 | </tr> |
aoqi@0 | 933 | </table> |
aoqi@0 | 934 | |
aoqi@0 | 935 | <h3>Initialization Script</h3> |
aoqi@0 | 936 | <p> |
aoqi@0 | 937 | jsdb 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 |
aoqi@0 | 938 | state during initialization script. |
aoqi@0 | 939 | </p> |
aoqi@0 | 940 | |
aoqi@0 | 941 | <h3>Sample scripts</h3> |
aoqi@0 | 942 | |
aoqi@0 | 943 | Semantics and knowledge of application classes (for eg. AppServer's classes) would be needed to create app specific |
aoqi@0 | 944 | scripts. The following script samples are app-independent and provide a flavour of kind of scripts that can be written. |
aoqi@0 | 945 | |
aoqi@0 | 946 | <h4>Script to print system properties of JVM</h4> |
aoqi@0 | 947 | |
aoqi@0 | 948 | <pre> |
aoqi@0 | 949 | <code> |
aoqi@0 | 950 | jvm.sysProps.toString() |
aoqi@0 | 951 | </code> |
aoqi@0 | 952 | </pre> |
aoqi@0 | 953 | |
aoqi@0 | 954 | <h4>Script to print JVM command line flags</h4> |
aoqi@0 | 955 | <pre> |
aoqi@0 | 956 | <code> |
aoqi@0 | 957 | jvm.flags.toString() |
aoqi@0 | 958 | </code> |
aoqi@0 | 959 | </pre> |
aoqi@0 | 960 | |
aoqi@0 | 961 | |
aoqi@0 | 962 | <h4>Script to print class-wise histogram of objects</h4> |
aoqi@0 | 963 | |
aoqi@0 | 964 | <pre> |
aoqi@0 | 965 | <code> |
aoqi@0 | 966 | |
aoqi@0 | 967 | // associate array to hold histogram |
aoqi@0 | 968 | var histo; |
aoqi@0 | 969 | function func(obj) { |
aoqi@0 | 970 | var classname = classof(obj).name; |
aoqi@0 | 971 | if (histo[classname] == undefined) { |
aoqi@0 | 972 | // first time we are visiting this class type |
aoqi@0 | 973 | histo[classname] = 1; |
aoqi@0 | 974 | } else { |
aoqi@0 | 975 | histo[classname]++; |
aoqi@0 | 976 | } |
aoqi@0 | 977 | } |
aoqi@0 | 978 | |
aoqi@0 | 979 | // iterate through java heap calling 'func' for each object |
aoqi@0 | 980 | jvm.heap.forEachObject(func); |
aoqi@0 | 981 | |
aoqi@0 | 982 | // print the histogram |
aoqi@0 | 983 | for (i in histo) { |
aoqi@0 | 984 | println('number of instances of ', i, ' = ', histo[i]); |
aoqi@0 | 985 | } |
aoqi@0 | 986 | |
aoqi@0 | 987 | </code> |
aoqi@0 | 988 | </pre> |
aoqi@0 | 989 | |
aoqi@0 | 990 | <h4>Script to print stack trace of all Java threads</h4> |
aoqi@0 | 991 | |
aoqi@0 | 992 | <pre> |
aoqi@0 | 993 | <code> |
aoqi@0 | 994 | |
aoqi@0 | 995 | function printStackTrace(t) { |
aoqi@0 | 996 | println(t.name); |
aoqi@0 | 997 | println(''); |
aoqi@0 | 998 | for (i in t.frames) { |
aoqi@0 | 999 | println(t.frames[i]); |
aoqi@0 | 1000 | } |
aoqi@0 | 1001 | println(''); |
aoqi@0 | 1002 | } |
aoqi@0 | 1003 | |
aoqi@0 | 1004 | // walk through the list of threads and call printStackTrace |
aoqi@0 | 1005 | // for each thread |
aoqi@0 | 1006 | for (o in jvm.threads) { |
aoqi@0 | 1007 | printStackTrace(jvm.threads[o]); |
aoqi@0 | 1008 | } |
aoqi@0 | 1009 | |
aoqi@0 | 1010 | |
aoqi@0 | 1011 | </code> |
aoqi@0 | 1012 | </pre> |
aoqi@0 | 1013 | |
aoqi@0 | 1014 | |
aoqi@0 | 1015 | <h4>Script to re-construct .class files for all non-bootstrap classes</h4> |
aoqi@0 | 1016 | |
aoqi@0 | 1017 | <pre> |
aoqi@0 | 1018 | <code> |
aoqi@0 | 1019 | |
aoqi@0 | 1020 | function dump(cl) { |
aoqi@0 | 1021 | if (!cl.isArrayClass && cl.classLoader != null) { |
aoqi@0 | 1022 | // not an array class and a non-bootstrap class |
aoqi@0 | 1023 | // create .class files in e:\tmp dir |
aoqi@0 | 1024 | dumpClass(cl, "e:\\tmp); |
aoqi@0 | 1025 | } else { |
aoqi@0 | 1026 | println("skipping bootstrap class ", cl.name); |
aoqi@0 | 1027 | } |
aoqi@0 | 1028 | } |
aoqi@0 | 1029 | |
aoqi@0 | 1030 | // walk thru heap and call callback for each java.lang.Class instance |
aoqi@0 | 1031 | jvm.heap.forEachObject(dump, "java.lang.Class"); |
aoqi@0 | 1032 | </code> |
aoqi@0 | 1033 | </pre> |
aoqi@0 | 1034 | |
aoqi@0 | 1035 | <h4>Script to print paths of all java.io.File's currently accessed</h4> |
aoqi@0 | 1036 | |
aoqi@0 | 1037 | <pre> |
aoqi@0 | 1038 | <code> |
aoqi@0 | 1039 | |
aoqi@0 | 1040 | function printFile(f) { |
aoqi@0 | 1041 | // construct a mirror java.io.File here and |
aoqi@0 | 1042 | // print absolute path here |
aoqi@0 | 1043 | println(mirror(f).getAbsolutePath()); |
aoqi@0 | 1044 | } |
aoqi@0 | 1045 | |
aoqi@0 | 1046 | jvm.heap.forEachObject(printFile, "java.io.File"); |
aoqi@0 | 1047 | |
aoqi@0 | 1048 | </code> |
aoqi@0 | 1049 | </pre> |
aoqi@0 | 1050 | |
aoqi@0 | 1051 | <h4>Script to print static fields of java.lang.Thread class</h4> |
aoqi@0 | 1052 | <pre> |
aoqi@0 | 1053 | <code> |
aoqi@0 | 1054 | |
aoqi@0 | 1055 | var threadClass = classof("java.lang.Thread"); |
aoqi@0 | 1056 | for (i in threadClass.statics) { |
aoqi@0 | 1057 | println(i, '=', threadClass.statics[i]); |
aoqi@0 | 1058 | } |
aoqi@0 | 1059 | |
aoqi@0 | 1060 | </code> |
aoqi@0 | 1061 | </pre> |
aoqi@0 | 1062 | |
aoqi@0 | 1063 | <h3>Low level interface (VM State)</h3> |
aoqi@0 | 1064 | |
aoqi@0 | 1065 | <p> |
aoqi@0 | 1066 | Low level jsdb interface works by <a href="http://www.mozilla.org/rhino/ScriptingJava.html">JavaScript-to-Java (previously known as "LiveConnect") |
aoqi@0 | 1067 | interface</a> provided by Rhino JavaScript engine. |
aoqi@0 | 1068 | </p> |
aoqi@0 | 1069 | |
aoqi@0 | 1070 | <h2>sapkg object</h2> |
aoqi@0 | 1071 | <p> |
aoqi@0 | 1072 | This object provides short names for SA package names. For eg. instead of writing |
aoqi@0 | 1073 | Packages.sun.jvm.hotspot.memory, we can write sapkg.memory. |
aoqi@0 | 1074 | </p> |
aoqi@0 | 1075 | |
aoqi@0 | 1076 | <h2>sa object</h2> |
aoqi@0 | 1077 | <p> |
aoqi@0 | 1078 | This object contains all SA singleton objects such as VM, Universe, SymbolTable, |
aoqi@0 | 1079 | SystemDictionary, ObjectHeap, CollectedHeap, Debugger, CDebugger (if available), |
aoqi@0 | 1080 | Interpreter, TypeDataBase and Threads. For eg. to access SymbolTable of Java debuggee, |
aoqi@0 | 1081 | we can use sa.symbolTable. User can execute the following code to get fields of this object. |
aoqi@0 | 1082 | </p> |
aoqi@0 | 1083 | <pre> |
aoqi@0 | 1084 | <code> |
aoqi@0 | 1085 | for (i in sa) { |
aoqi@0 | 1086 | println(i); |
aoqi@0 | 1087 | } |
aoqi@0 | 1088 | </code> |
aoqi@0 | 1089 | </pre> |
aoqi@0 | 1090 | |
aoqi@0 | 1091 | <h4>Heap Iterators</h4> |
aoqi@0 | 1092 | <dl> |
aoqi@0 | 1093 | <dt>forEachOop(callback)</dt> |
aoqi@0 | 1094 | <dd>calls a callback function for each Oop in Java heap</dd> |
aoqi@0 | 1095 | <dt>forEachOopOfKlass(callback, klass, [includeSubtypes])</dt> |
aoqi@0 | 1096 | <dd>calls a callback function for each Oop of a give Klass type |
aoqi@0 | 1097 | Optinally, third argument can specify whether to include subtype Oops |
aoqi@0 | 1098 | or not. |
aoqi@0 | 1099 | </dd> |
aoqi@0 | 1100 | </dl> |
aoqi@0 | 1101 | |
aoqi@0 | 1102 | <h4>System Dictionary Access</h4> |
aoqi@0 | 1103 | <dl> |
aoqi@0 | 1104 | <dt>forEachKlass(callback)</dt> |
aoqi@0 | 1105 | <dd>calls a callback function for each Klass in Java heap</dd> |
aoqi@0 | 1106 | <dt>forEachKlassAndLoader(callback)</dt> |
aoqi@0 | 1107 | <dd> |
aoqi@0 | 1108 | calls callback with Klass and initiating loader (Oop) for System dictionary |
aoqi@0 | 1109 | entry. |
aoqi@0 | 1110 | </dd> |
aoqi@0 | 1111 | <dt>forEachPrimArrayKlass(callback)</dt> |
aoqi@0 | 1112 | <dd> |
aoqi@0 | 1113 | calls callback with Klass and initiating loader (Oop) for each |
aoqi@0 | 1114 | primitive array Klass in the system. |
aoqi@0 | 1115 | </dd> |
aoqi@0 | 1116 | <dt>findInstanceKlass(name)</dt> |
aoqi@0 | 1117 | <dd> |
aoqi@0 | 1118 | finds the first instance klass with given name from System dictionary |
aoqi@0 | 1119 | </dd> |
aoqi@0 | 1120 | </dl> |
aoqi@0 | 1121 | |
aoqi@0 | 1122 | <h4>Thread, Frame Iterators</h4> |
aoqi@0 | 1123 | <dl> |
aoqi@0 | 1124 | <dt>forEachJavaThread(callback)</dt> |
aoqi@0 | 1125 | <dd>calls callback for each Java Thread</dd> |
aoqi@0 | 1126 | <dt>forEachFrame(javaThread, callback)</dt> |
aoqi@0 | 1127 | <dd>calls callback for each Frame of a given JavaThread</dd> |
aoqi@0 | 1128 | <dt>forEachVFrame(javaThread, callback)</dt> |
aoqi@0 | 1129 | <dd>calls callback for each JavaVFrame of a given JavaThread</dd> |
aoqi@0 | 1130 | <dt>forEachThread(callback)</dt> |
aoqi@0 | 1131 | <dd>calls callback for each (native) ThreadProxy (obtained by CDebugger.getThreadList) |
aoqi@0 | 1132 | </dd> |
aoqi@0 | 1133 | <dt>forEachCFrame(threadProxy, callback)</dt> |
aoqi@0 | 1134 | <dd> |
aoqi@0 | 1135 | calls callback for each CFrame of a given ThreadProxy object |
aoqi@0 | 1136 | </dd> |
aoqi@0 | 1137 | </dl> |
aoqi@0 | 1138 | |
aoqi@0 | 1139 | <h4>Code blobs, Interpreter codelets</h4> |
aoqi@0 | 1140 | <dl> |
aoqi@0 | 1141 | <dt>forEachCodeBlob(callback)</dt> |
aoqi@0 | 1142 | <dd> |
aoqi@0 | 1143 | calls callback with each code blob in code cache |
aoqi@0 | 1144 | </dd> |
aoqi@0 | 1145 | <dt>findCodeBlob(address)</dt> |
aoqi@0 | 1146 | <dd> |
aoqi@0 | 1147 | finds the code blob, if any, that contains the given address. |
aoqi@0 | 1148 | Returns null, on failure. |
aoqi@0 | 1149 | </dd> |
aoqi@0 | 1150 | <dt>findNMethod(address)</dt> |
aoqi@0 | 1151 | <dd> |
aoqi@0 | 1152 | finds the NMethod that contains given address. |
aoqi@0 | 1153 | </dd> |
aoqi@0 | 1154 | <dt>pcDescAt(addr)</dt> |
aoqi@0 | 1155 | <dd> |
aoqi@0 | 1156 | returns PCDesc at given address or null. |
aoqi@0 | 1157 | </dd> |
aoqi@0 | 1158 | <dt>forEachInterpCodelet(callbacl)</dt> |
aoqi@0 | 1159 | <dd> |
aoqi@0 | 1160 | calls callback with each Interpreter codelet |
aoqi@0 | 1161 | </dd> |
aoqi@0 | 1162 | </dl> |
aoqi@0 | 1163 | |
aoqi@0 | 1164 | <h4>VM structs, constants</h4> |
aoqi@0 | 1165 | <dl> |
aoqi@0 | 1166 | <dt>forEachType(callback)</dt> |
aoqi@0 | 1167 | <dd> |
aoqi@0 | 1168 | calls callback for each Type in VM's type database |
aoqi@0 | 1169 | </dd> |
aoqi@0 | 1170 | <dt>forEachVMIntConst(callback)</dt> |
aoqi@0 | 1171 | <dd> |
aoqi@0 | 1172 | calls callback for each named integer constant. passes name |
aoqi@0 | 1173 | as argument. |
aoqi@0 | 1174 | </dd> |
aoqi@0 | 1175 | <dt>forEachVMLongConst(callback)</dt> |
aoqi@0 | 1176 | <dd> |
aoqi@0 | 1177 | calls callback for each named long constant. passes name |
aoqi@0 | 1178 | as argument. |
aoqi@0 | 1179 | </dd> |
aoqi@0 | 1180 | <dt>findVMType(name)</dt> |
aoqi@0 | 1181 | <dd> |
aoqi@0 | 1182 | finds a VM type by name. returns null if no known Type of given name |
aoqi@0 | 1183 | exists in type database. |
aoqi@0 | 1184 | </dd> |
aoqi@0 | 1185 | <dt>findVMIntConst(name)</dt> |
aoqi@0 | 1186 | <dd> |
aoqi@0 | 1187 | finds an integer constant in type data base by name. |
aoqi@0 | 1188 | </dd> |
aoqi@0 | 1189 | <dt>findVMLongConst(name)</dt> |
aoqi@0 | 1190 | <dd> |
aoqi@0 | 1191 | finds an long constant in type data base by name. |
aoqi@0 | 1192 | </dd> |
aoqi@0 | 1193 | <dt>vmTypeof(addr)</dt> |
aoqi@0 | 1194 | <dd> |
aoqi@0 | 1195 | returns VM type of object at 'addr' if any. Else, returns null. |
aoqi@0 | 1196 | </dd> |
aoqi@0 | 1197 | <dt>isOfVMType(addr, type)</dt> |
aoqi@0 | 1198 | <dd> |
aoqi@0 | 1199 | returns whether object at 'addr' is of VM type 'type' or not. |
aoqi@0 | 1200 | </dd> |
aoqi@0 | 1201 | <dt>printVMType(type, addr)</dt> |
aoqi@0 | 1202 | <dd> |
aoqi@0 | 1203 | prints 'addr' as VM object of type 'type' |
aoqi@0 | 1204 | </dd> |
aoqi@0 | 1205 | <dt>print<i>XXX</i>(addr)</dt> |
aoqi@0 | 1206 | <dd> |
aoqi@0 | 1207 | For each VM type, these functions are defined. For eg. there is printUniverse, |
aoqi@0 | 1208 | printSystemDictionary etc. are available. Without 'addr' being passed static fields are printed. With 'addr' param being passed, instance fields are printed. |
aoqi@0 | 1209 | </dd> |
aoqi@0 | 1210 | </dl> |
aoqi@0 | 1211 | |
aoqi@0 | 1212 | <h4>Low level debugger facilities</h4> |
aoqi@0 | 1213 | <dl> |
aoqi@0 | 1214 | <dt>num2addr(number)</dt> |
aoqi@0 | 1215 | <dd> |
aoqi@0 | 1216 | converts a (long) number to SA Address instance |
aoqi@0 | 1217 | </dd> |
aoqi@0 | 1218 | <dt>str2addr(string)</dt> |
aoqi@0 | 1219 | <dd> |
aoqi@0 | 1220 | converts a given hex string to SA Address instance |
aoqi@0 | 1221 | </dd> |
aoqi@0 | 1222 | <dt>any2addr(any)</dt> |
aoqi@0 | 1223 | <dd> |
aoqi@0 | 1224 | Takes a number or a string or an Address and returns |
aoqi@0 | 1225 | an Address instance. For other types, returns 'undefined' |
aoqi@0 | 1226 | </dd> |
aoqi@0 | 1227 | <dt>addr2str(addr)</dt> |
aoqi@0 | 1228 | <dd> |
aoqi@0 | 1229 | converts a given Address instance to a hex string |
aoqi@0 | 1230 | </dd> |
aoqi@0 | 1231 | <dt>addr2num(addr)</dt> |
aoqi@0 | 1232 | <dd> |
aoqi@0 | 1233 | converts a given Address instance to a (long) number |
aoqi@0 | 1234 | </dd> |
aoqi@0 | 1235 | <dt>sym2addr(library, symbol)</dt> |
aoqi@0 | 1236 | <dd> |
aoqi@0 | 1237 | returns Address of a given symbol in a given library (shared object or DLL) |
aoqi@0 | 1238 | Example: sym2addr('jvm.dll', 'JNI_CreateJavaVM') |
aoqi@0 | 1239 | <dt>addr2sym(addr)</dt> |
aoqi@0 | 1240 | <dd> |
aoqi@0 | 1241 | Returns nearest symbol to a given address (if any). If no such symbol is found, |
aoqi@0 | 1242 | returns the given address as a string. |
aoqi@0 | 1243 | </dd> |
aoqi@0 | 1244 | <dt>readBytesAt(addr, num)</dt> |
aoqi@0 | 1245 | <dd> |
aoqi@0 | 1246 | returns 'num' bytes at 'addr' as a Java byte[] |
aoqi@0 | 1247 | </dd> |
aoqi@0 | 1248 | <dt>readWordsAt(addr, num)</dt> |
aoqi@0 | 1249 | <dd> |
aoqi@0 | 1250 | returns 'num' words at 'addr' as a Java long[] |
aoqi@0 | 1251 | </dd> |
aoqi@0 | 1252 | <dt>readCStrAt(addr)</dt> |
aoqi@0 | 1253 | <dd> |
aoqi@0 | 1254 | returns 'C' String at given address |
aoqi@0 | 1255 | </dd> |
aoqi@0 | 1256 | <dt>readCStrLen(addr)</dt> |
aoqi@0 | 1257 | <dd> |
aoqi@0 | 1258 | returns the length of the 'C' String at given address |
aoqi@0 | 1259 | </dd> |
aoqi@0 | 1260 | <dt>readRegs(threadProxy)</dt> |
aoqi@0 | 1261 | <dd> |
aoqi@0 | 1262 | returns register set (of Thread Context) of a given thread specified |
aoqi@0 | 1263 | by threadProxy. return value is an associate array having name-value pairs |
aoqi@0 | 1264 | of registers. |
aoqi@0 | 1265 | </dd> |
aoqi@0 | 1266 | <dt>regs(threadProxy)</dt> |
aoqi@0 | 1267 | <dd> |
aoqi@0 | 1268 | prints register set of a given thread. |
aoqi@0 | 1269 | </dd> |
aoqi@0 | 1270 | <dt>mem(addr, [num])</dt> |
aoqi@0 | 1271 | <dd> |
aoqi@0 | 1272 | prints 'num' words (address size) at 'addr'. Prints nearest symbol for address, if found. |
aoqi@0 | 1273 | </dd> |
aoqi@0 | 1274 | <dt>dis(addr, [num])</dt> |
aoqi@0 | 1275 | <dd>prints native code disassembly of 'num' bytes at given address 'addr'. |
aoqi@0 | 1276 | Default value of 'num' is 4. This automatically detects whether the given address |
aoqi@0 | 1277 | inside a nmethod. If so, it prints safepoint info, entry points , method signature etc. |
aoqi@0 | 1278 | of the nmethod. |
aoqi@0 | 1279 | </dd> |
aoqi@0 | 1280 | <dt>jdis(method [or addr])</dt> |
aoqi@0 | 1281 | <dd> |
aoqi@0 | 1282 | prints Java bytecode disassembly for given method Oop or address of a method Oop. |
aoqi@0 | 1283 | </dd> |
aoqi@0 | 1284 | <dt>nmethoddis(nmethod)</dt> |
aoqi@0 | 1285 | <dd> |
aoqi@0 | 1286 | prints disassembly of given nmethod object. Note that you don't have to call this directly |
aoqi@0 | 1287 | instead use 'dis'. |
aoqi@0 | 1288 | </dd> |
aoqi@0 | 1289 | <dt>where</dt> |
aoqi@0 | 1290 | <dd> |
aoqi@0 | 1291 | prints Java stack trace for all Java threads |
aoqi@0 | 1292 | </dd> |
aoqi@0 | 1293 | </dl> |
aoqi@0 | 1294 | |
aoqi@0 | 1295 | <h4>Miscellaneous</h4> |
aoqi@0 | 1296 | <dl> |
aoqi@0 | 1297 | <dt>addr2oop(addr)</dt> |
aoqi@0 | 1298 | <dd> |
aoqi@0 | 1299 | converts a given address to a Oop object |
aoqi@0 | 1300 | </dd> |
aoqi@0 | 1301 | <dt>oop2addr(oop)</dt> |
aoqi@0 | 1302 | <dd> |
aoqi@0 | 1303 | returns address of a given Oop object |
aoqi@0 | 1304 | </dd> |
aoqi@0 | 1305 | <dt>isOfVMType(addr, type)</dt> |
aoqi@0 | 1306 | <dd> |
aoqi@0 | 1307 | returns whether the given 'addr' points to a (C++) VM object of specified |
aoqi@0 | 1308 | type. type may be specified by SA Type object or string name of the type. |
aoqi@0 | 1309 | </dd> |
aoqi@0 | 1310 | <dt>newVMObject(addr)</dt> |
aoqi@0 | 1311 | <dd> |
aoqi@0 | 1312 | returns instance of SA object for a given address (similar to SA VirtualConstructor |
aoqi@0 | 1313 | interface). |
aoqi@0 | 1314 | </dd> |
aoqi@0 | 1315 | <dt>vmobj2addr(vmobject)</dt> |
aoqi@0 | 1316 | <dd> |
aoqi@0 | 1317 | returns Address represented by a given SA VMObject |
aoqi@0 | 1318 | </dd> |
aoqi@0 | 1319 | <dt>addr2vmobj(addr)</dt> |
aoqi@0 | 1320 | <dd>same as newVMObject(addr)</dd> |
aoqi@0 | 1321 | <dt>whatis(addr)</dt> |
aoqi@0 | 1322 | <dd> |
aoqi@0 | 1323 | returns string description of given address (using SA FindPointer and guess type API). |
aoqi@0 | 1324 | <dt>isOop(addr)</dt> |
aoqi@0 | 1325 | <dd> |
aoqi@0 | 1326 | returns whether a given address is a valid Oop address or not |
aoqi@0 | 1327 | </dd> |
aoqi@0 | 1328 | </dl> |
aoqi@0 | 1329 | |
aoqi@0 | 1330 | <h4>Moving b/w jsdb low level and high level interfaces</h4> |
aoqi@0 | 1331 | |
aoqi@0 | 1332 | <p> |
aoqi@0 | 1333 | Java objects of debuggee are represented by different script wrappers in high level |
aoqi@0 | 1334 | interface. In the low-level interface these are instances of SA Oop class or its' |
aoqi@0 | 1335 | subclass. To move b/w low-level and high-level interfaces the following functions may |
aoqi@0 | 1336 | be used |
aoqi@0 | 1337 | </p> |
aoqi@0 | 1338 | <dl> |
aoqi@0 | 1339 | <dt>oop2obj(oop)</dt> |
aoqi@0 | 1340 | <dd> |
aoqi@0 | 1341 | converts a given Oop object to a high-level wrapper object |
aoqi@0 | 1342 | </dd> |
aoqi@0 | 1343 | <dt>obj2oop(obj)</dt> |
aoqi@0 | 1344 | <dd> |
aoqi@0 | 1345 | converts a jsdb high level wrapper to underlying Oop instance |
aoqi@0 | 1346 | </dd> |
aoqi@0 | 1347 | </dl> |
aoqi@0 | 1348 | |
aoqi@0 | 1349 | <h3>JavaScript tips</h3> |
aoqi@0 | 1350 | |
aoqi@0 | 1351 | <ul> |
aoqi@0 | 1352 | <li>to know properties, functions of any object, use the script |
aoqi@0 | 1353 | <pre> |
aoqi@0 | 1354 | <core> |
aoqi@0 | 1355 | for(i in object) { println(i); } |
aoqi@0 | 1356 | </code> |
aoqi@0 | 1357 | </pre> |
aoqi@0 | 1358 | <li>to view the source code of any function, just type the name of |
aoqi@0 | 1359 | function in jsdb prompt |
aoqi@0 | 1360 | <li>to view global functions, properties, run |
aoqi@0 | 1361 | <pre> |
aoqi@0 | 1362 | <code> |
aoqi@0 | 1363 | for(i in this) { println(i); } |
aoqi@0 | 1364 | </code> |
aoqi@0 | 1365 | </pre> |
aoqi@0 | 1366 | </ul> |
aoqi@0 | 1367 | |
aoqi@0 | 1368 | </body> |
aoqi@0 | 1369 | </html> |