/* * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others * at JavaSoft/Sun. */ var hatPkg = Packages.com.sun.tools.hat.internal; /** * This is JavaScript interface for heap analysis using HAT * (Heap Analysis Tool). HAT classes are refered from * this file. In particular, refer to classes in hat.model * package. * * HAT model objects are wrapped as convenient script objects so that * fields may be accessed in natural syntax. For eg. Java fields can be * accessed with obj.field_name syntax and array elements can be accessed * with array[index] syntax. */ // returns an enumeration that wraps elements of// the input enumeration elements.function wrapperEnumeration(e) { return new java.util.Enumeration() { hasMoreElements: function() { return e.hasMoreElements(); }, nextElement: function() { return wrapJavaValue(e.nextElement()); } };} // returns an enumeration that filters out elements// of input enumeration using the filter function.function filterEnumeration(e, func, wrap) { var next = undefined; var index = 0; function findNext() { var tmp; while (e.hasMoreElements()) { tmp = e.nextElement(); index++; if (wrap) { tmp = wrapJavaValue(tmp); } if (func(tmp, index, e)) { next = tmp; return; } } } return new java.util.Enumeration() { hasMoreElements: function() { findNext(); return next != undefined; }, nextElement: function() { if (next == undefined) { // user may not have called hasMoreElements? findNext(); } if (next == undefined) { throw "NoSuchElementException"; } var res = next; next = undefined; return res; } };} // enumeration that has no elements ..var emptyEnumeration = new java.util.Enumeration() { hasMoreElements: function() { return false; }, nextElement: function() { throw "NoSuchElementException"; } }; function wrapRoot(root) { if (root) { return { id: root.idString, description: root.description, referrer: wrapJavaValue(root.referer), type: root.typeName }; } else { return null; }} function JavaClassProto() { function jclass(obj) { return obj['wrapped-object']; } // return whether given class is subclass of this class or not this.isSubclassOf = function(other) { var tmp = jclass(this); var otherid = objectid(other); while (tmp != null) { if (otherid.equals(tmp.idString)) { return true; } tmp = tmp.superclass; } return false; } // return whether given class is superclass of this class or not this.isSuperclassOf = function(other) { return other.isSubclassOf(this); } // includes direct and indirect superclasses this.superclasses = function() { var res = new Array(); var tmp = this.superclass; while (tmp != null) { res[res.length] = tmp; tmp = tmp.superclass; } return res; } /** * Returns an array containing subclasses of this class. * * @param indirect should include indirect subclasses or not. * default is true. */ this.subclasses = function(indirect) { if (indirect == undefined) indirect = true; var classes = jclass(this).subclasses; var res = new Array(); for (var i in classes) { var subclass = wrapJavaValue(classes[i]); res[res.length] = subclass; if (indirect) { res = res.concat(subclass.subclasses()); } } return res; } this.toString = function() { return jclass(this).toString(); }} var theJavaClassProto = new JavaClassProto(); // Script wrapper for HAT model objects, values.// wraps a Java value as appropriate for script objectfunction wrapJavaValue(thing) { if (thing == null || thing == undefined || thing instanceof hatPkg.model.HackJavaValue) { return null; } if (thing instanceof hatPkg.model.JavaValue) { // map primitive values to closest JavaScript primitives if (thing instanceof hatPkg.model.JavaBoolean) { return thing.toString() == "true"; } else if (thing instanceof hatPkg.model.JavaChar) { return thing.toString() + ''; } else { return java.lang.Double.parseDouble(thing.toString()); } } else { // wrap Java object as script object return wrapJavaObject(thing); }} // wrap Java object with appropriate script objectfunction wrapJavaObject(thing) { // HAT Java model object wrapper. Handles all cases // (instance, object/primitive array and Class objects) function javaObject(jobject) { // FIXME: Do I need this? or can I assume that these would // have been resolved already? if (jobject instanceof hatPkg.model.JavaObjectRef) { jobject = jobject.dereference(); if (jobject instanceof hatPkg.model.HackJavaValue) { print(jobject); return null; } } if (jobject instanceof hatPkg.model.JavaObject) { return new JavaObjectWrapper(jobject); } else if (jobject instanceof hatPkg.model.JavaClass) { return new JavaClassWrapper(jobject); } else if (jobject instanceof hatPkg.model.JavaObjectArray) { return new JavaObjectArrayWrapper(jobject); } else if (jobject instanceof hatPkg.model.JavaValueArray) { return new JavaValueArrayWrapper(jobject); } else { print("unknown heap object type: " + jobject.getClass()); return jobject; } } // returns wrapper for Java instances function JavaObjectWrapper(instance) { var things = instance.fields; var fields = instance.clazz.fieldsForInstance; // instance fields can be accessed in natural syntax return new JSAdapter() { __getIds__ : function() { var res = new Array(fields.length); for (var i in fields) { res[i] = fields[i].name; } return res; }, __has__ : function(name) { for (var i in fields) { if (name == fields[i].name) return true; } return name == 'class' || name == 'toString' || name == 'wrapped-object'; }, __get__ : function(name) { for (var i in fields) { if(fields[i].name == name) { return wrapJavaValue(things[i]); } } if (name == 'class') { return wrapJavaValue(instance.clazz); } else if (name == 'toString') { return function() { return instance.toString(); } } else if (name == 'wrapped-object') { return instance; } return undefined; } } } // return wrapper for Java Class objects function JavaClassWrapper(jclass) { var fields = jclass.statics; // to access static fields of given Class cl, use // cl.statics.<static-field-name> syntax this.statics = new JSAdapter() { __getIds__ : function() { var res = new Array(fields.length); for (var i in fields) { res[i] = fields[i].field.name; } return res; }, __has__ : function(name) { for (var i in fields) { if (name == fields[i].field.name) { return true; } } return theJavaClassProto[name] != undefined; }, __get__ : function(name) { for (var i in fields) { if (name == fields[i].field.name) { return wrapJavaValue(fields[i].value); } } return theJavaClassProto[name]; } } if (jclass.superclass != null) { this.superclass = wrapJavaValue(jclass.superclass); } else { this.superclass = null; } this.loader = wrapJavaValue(jclass.getLoader()); this.signers = wrapJavaValue(jclass.getSigners()); this.protectionDomain = wrapJavaValue(jclass.getProtectionDomain()); this.instanceSize = jclass.instanceSize; this.name = jclass.name; this.fields = jclass.fields; this['wrapped-object'] = jclass; this.__proto__ = this.statics; } // returns wrapper for Java object arrays function JavaObjectArrayWrapper(array) { var elements = array.elements; // array elements can be accessed in natural syntax // also, 'length' property is supported. return new JSAdapter() { __getIds__ : function() { var res = new Array(elements.length); for (var i = 0; i < elements.length; i++) { res[i] = i; } return res; }, __has__: function(name) { return (typeof(name) == 'number' && name >= 0 && name < elements.length) || name == 'length' || name == 'class' || name == 'toString' || name == 'wrapped-object'; }, __get__ : function(name) { if (typeof(name) == 'number' && name >= 0 && name < elements.length) { return wrapJavaValue(elements[name]); } else if (name == 'length') { return elements.length; } else if (name == 'class') { return wrapJavaValue(array.clazz); } else if (name == 'toString') { return function() { return array.toString(); } } else if (name == 'wrapped-object') { return array; } else { return undefined; } } } } // returns wrapper for Java primitive arrays function JavaValueArrayWrapper(array) { var type = String(java.lang.Character.toString(array.elementType)); var elements = array.elements; // array elements can be accessed in natural syntax // also, 'length' property is supported. return new JSAdapter() { __getIds__ : function() { var r = new Array(array.length); for (var i = 0; i < array.length; i++) { r[i] = i; } return r; }, __has__: function(name) { return (typeof(name) == 'number' && name >= 0 && name < array.length) || name == 'length' || name == 'class' || name == 'toString' || name == 'wrapped-object'; }, __get__: function(name) { if (typeof(name) == 'number' && name >= 0 && name < array.length) { return elements[name]; } if (name == 'length') { return array.length; } else if (name == 'toString') { return function() { return array.valueString(true); } } else if (name == 'wrapped-object') { return array; } else if (name == 'class') { return wrapJavaValue(array.clazz); } else { return undefined; } } } } return javaObject(thing);} // unwrap a script object to corresponding HAT objectfunction unwrapJavaObject(jobject) { if (!(jobject instanceof hatPkg.model.JavaHeapObject)) { try { jobject = jobject["wrapped-object"]; } catch (e) { print("unwrapJavaObject: " + jobject + ", " + e); jobject = undefined; } } return jobject;} /** * readHeapDump parses a heap dump file and returns script wrapper object. * * @param file Heap dump file name * @param stack flag to tell if allocation site traces are available * @param refs flag to tell if backward references are needed or not * @param debug debug level for HAT * @return heap as a JavaScript object */function readHeapDump(file, stack, refs, debug) { // default value of debug is 0 if (!debug) debug = 0; // by default, we assume no stack traces if (!stack) stack = false; // by default, backward references are resolved if (!refs) refs = true; // read the heap dump var heap = hatPkg.parser.HprofReader.readFile(file, stack, debug); // resolve it heap.resolve(refs); // wrap Snapshot as convenient script object return wrapHeapSnapshot(heap);} /** * The result object supports the following methods: * * forEachClass -- calls a callback for each Java Class * forEachObject -- calls a callback for each Java object * findClass -- finds Java Class of given name * findObject -- finds object from given object id * objects -- returns all objects of given class as an enumeration * classes -- returns all classes in the heap as an enumeration * reachables -- returns all objects reachable from a given object * livepaths -- returns an array of live paths because of which an * object alive. * describeRef -- returns description for a reference from a 'from' * object to a 'to' object. */function wrapHeapSnapshot(heap) { function getClazz(clazz) { if (clazz == undefined) clazz = "java.lang.Object"; var type = typeof(clazz); if (type == "string") { clazz = heap.findClass(clazz); } else if (type == "object") { clazz = unwrapJavaObject(clazz); } else { throw "class expected";; } return clazz; } // return heap as a script object with useful methods. return { snapshot: heap, /** * Class iteration: Calls callback function for each * Java Class in the heap. Default callback function * is 'print'. If callback returns true, the iteration * is stopped. * * @param callback function to be called. */ forEachClass: function(callback) { if (callback == undefined) callback = print; var classes = this.snapshot.classes; while (classes.hasMoreElements()) { if (callback(wrapJavaValue(classes.nextElement()))) return; } },Lines 1–500 of 1463. Load more
/* * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others * at JavaSoft/Sun. */ var hatPkg = Packages.com.sun.tools.hat.internal; /** * This is JavaScript interface for heap analysis using HAT * (Heap Analysis Tool). HAT classes are refered from * this file. In particular, refer to classes in hat.model * package. * * HAT model objects are wrapped as convenient script objects so that * fields may be accessed in natural syntax. For eg. Java fields can be * accessed with obj.field_name syntax and array elements can be accessed * with array[index] syntax. */ // returns an enumeration that wraps elements of // the input enumeration elements. function wrapperEnumeration(e) { return new java.util.Enumeration() { hasMoreElements: function() { return e.hasMoreElements(); }, nextElement: function() { return wrapJavaValue(e.nextElement()); } }; } // returns an enumeration that filters out elements // of input enumeration using the filter function. function filterEnumeration(e, func, wrap) { var next = undefined; var index = 0; function findNext() { var tmp; while (e.hasMoreElements()) { tmp = e.nextElement(); index++; if (wrap) { tmp = wrapJavaValue(tmp); } if (func(tmp, index, e)) { next = tmp; return; } } } return new java.util.Enumeration() { hasMoreElements: function() { findNext(); return next != undefined; }, nextElement: function() { if (next == undefined) { // user may not have called hasMoreElements? findNext(); } if (next == undefined) { throw "NoSuchElementException"; } var res = next; next = undefined; return res; } }; } // enumeration that has no elements .. var emptyEnumeration = new java.util.Enumeration() { hasMoreElements: function() { return false; }, nextElement: function() { throw "NoSuchElementException"; } }; function wrapRoot(root) { if (root) { return { id: root.idString, description: root.description, referrer: wrapJavaValue(root.referer), type: root.typeName }; } else { return null; } } function JavaClassProto() { function jclass(obj) { return obj['wrapped-object']; } // return whether given class is subclass of this class or not this.isSubclassOf = function(other) { var tmp = jclass(this); var otherid = objectid(other); while (tmp != null) { if (otherid.equals(tmp.idString)) { return true; } tmp = tmp.superclass; } return false; } // return whether given class is superclass of this class or not this.isSuperclassOf = function(other) { return other.isSubclassOf(this); } // includes direct and indirect superclasses this.superclasses = function() { var res = new Array(); var tmp = this.superclass; while (tmp != null) { res[res.length] = tmp; tmp = tmp.superclass; } return res; } /** * Returns an array containing subclasses of this class. * * @param indirect should include indirect subclasses or not. * default is true. */ this.subclasses = function(indirect) { if (indirect == undefined) indirect = true; var classes = jclass(this).subclasses; var res = new Array(); for (var i in classes) { var subclass = wrapJavaValue(classes[i]); res[res.length] = subclass; if (indirect) { res = res.concat(subclass.subclasses()); } } return res; } this.toString = function() { return jclass(this).toString(); } } var theJavaClassProto = new JavaClassProto(); // Script wrapper for HAT model objects, values. // wraps a Java value as appropriate for script object function wrapJavaValue(thing) { if (thing == null || thing == undefined || thing instanceof hatPkg.model.HackJavaValue) { return null; } if (thing instanceof hatPkg.model.JavaValue) { // map primitive values to closest JavaScript primitives if (thing instanceof hatPkg.model.JavaBoolean) { return thing.toString() == "true"; } else if (thing instanceof hatPkg.model.JavaChar) { return thing.toString() + ''; } else { return java.lang.Double.parseDouble(thing.toString()); } } else { // wrap Java object as script object return wrapJavaObject(thing); } } // wrap Java object with appropriate script object function wrapJavaObject(thing) { // HAT Java model object wrapper. Handles all cases // (instance, object/primitive array and Class objects) function javaObject(jobject) { // FIXME: Do I need this? or can I assume that these would // have been resolved already? if (jobject instanceof hatPkg.model.JavaObjectRef) { jobject = jobject.dereference(); if (jobject instanceof hatPkg.model.HackJavaValue) { print(jobject); return null; } } if (jobject instanceof hatPkg.model.JavaObject) { return new JavaObjectWrapper(jobject); } else if (jobject instanceof hatPkg.model.JavaClass) { return new JavaClassWrapper(jobject); } else if (jobject instanceof hatPkg.model.JavaObjectArray) { return new JavaObjectArrayWrapper(jobject); } else if (jobject instanceof hatPkg.model.JavaValueArray) { return new JavaValueArrayWrapper(jobject); } else { print("unknown heap object type: " + jobject.getClass()); return jobject; } } // returns wrapper for Java instances function JavaObjectWrapper(instance) { var things = instance.fields; var fields = instance.clazz.fieldsForInstance; // instance fields can be accessed in natural syntax return new JSAdapter() { __getIds__ : function() { var res = new Array(fields.length); for (var i in fields) { res[i] = fields[i].name; } return res; }, __has__ : function(name) { for (var i in fields) { if (name == fields[i].name) return true; } return name == 'class' || name == 'toString' || name == 'wrapped-object'; }, __get__ : function(name) { for (var i in fields) { if(fields[i].name == name) { return wrapJavaValue(things[i]); } } if (name == 'class') { return wrapJavaValue(instance.clazz); } else if (name == 'toString') { return function() { return instance.toString(); } } else if (name == 'wrapped-object') { return instance; } return undefined; } } } // return wrapper for Java Class objects function JavaClassWrapper(jclass) { var fields = jclass.statics; // to access static fields of given Class cl, use // cl.statics.<static-field-name> syntax this.statics = new JSAdapter() { __getIds__ : function() { var res = new Array(fields.length); for (var i in fields) { res[i] = fields[i].field.name; } return res; }, __has__ : function(name) { for (var i in fields) { if (name == fields[i].field.name) { return true; } } return theJavaClassProto[name] != undefined; }, __get__ : function(name) { for (var i in fields) { if (name == fields[i].field.name) { return wrapJavaValue(fields[i].value); } } return theJavaClassProto[name]; } } if (jclass.superclass != null) { this.superclass = wrapJavaValue(jclass.superclass); } else { this.superclass = null; } this.loader = wrapJavaValue(jclass.getLoader()); this.signers = wrapJavaValue(jclass.getSigners()); this.protectionDomain = wrapJavaValue(jclass.getProtectionDomain()); this.instanceSize = jclass.instanceSize; this.name = jclass.name; this.fields = jclass.fields; this['wrapped-object'] = jclass; this.__proto__ = this.statics; } // returns wrapper for Java object arrays function JavaObjectArrayWrapper(array) { var elements = array.elements; // array elements can be accessed in natural syntax // also, 'length' property is supported. return new JSAdapter() { __getIds__ : function() { var res = new Array(elements.length); for (var i = 0; i < elements.length; i++) { res[i] = i; } return res; }, __has__: function(name) { return (typeof(name) == 'number' && name >= 0 && name < elements.length) || name == 'length' || name == 'class' || name == 'toString' || name == 'wrapped-object'; }, __get__ : function(name) { if (typeof(name) == 'number' && name >= 0 && name < elements.length) { return wrapJavaValue(elements[name]); } else if (name == 'length') { return elements.length; } else if (name == 'class') { return wrapJavaValue(array.clazz); } else if (name == 'toString') { return function() { return array.toString(); } } else if (name == 'wrapped-object') { return array; } else { return undefined; } } } } // returns wrapper for Java primitive arrays function JavaValueArrayWrapper(array) { var type = String(java.lang.Character.toString(array.elementType)); var elements = array.elements; // array elements can be accessed in natural syntax // also, 'length' property is supported. return new JSAdapter() { __getIds__ : function() { var r = new Array(array.length); for (var i = 0; i < array.length; i++) { r[i] = i; } return r; }, __has__: function(name) { return (typeof(name) == 'number' && name >= 0 && name < array.length) || name == 'length' || name == 'class' || name == 'toString' || name == 'wrapped-object'; }, __get__: function(name) { if (typeof(name) == 'number' && name >= 0 && name < array.length) { return elements[name]; } if (name == 'length') { return array.length; } else if (name == 'toString') { return function() { return array.valueString(true); } } else if (name == 'wrapped-object') { return array; } else if (name == 'class') { return wrapJavaValue(array.clazz); } else { return undefined; } } } } return javaObject(thing); } // unwrap a script object to corresponding HAT object function unwrapJavaObject(jobject) { if (!(jobject instanceof hatPkg.model.JavaHeapObject)) { try { jobject = jobject["wrapped-object"]; } catch (e) { print("unwrapJavaObject: " + jobject + ", " + e); jobject = undefined; } } return jobject; } /** * readHeapDump parses a heap dump file and returns script wrapper object. * * @param file Heap dump file name * @param stack flag to tell if allocation site traces are available * @param refs flag to tell if backward references are needed or not * @param debug debug level for HAT * @return heap as a JavaScript object */ function readHeapDump(file, stack, refs, debug) { // default value of debug is 0 if (!debug) debug = 0; // by default, we assume no stack traces if (!stack) stack = false; // by default, backward references are resolved if (!refs) refs = true; // read the heap dump var heap = hatPkg.parser.HprofReader.readFile(file, stack, debug); // resolve it heap.resolve(refs); // wrap Snapshot as convenient script object return wrapHeapSnapshot(heap); } /** * The result object supports the following methods: * * forEachClass -- calls a callback for each Java Class * forEachObject -- calls a callback for each Java object * findClass -- finds Java Class of given name * findObject -- finds object from given object id * objects -- returns all objects of given class as an enumeration * classes -- returns all classes in the heap as an enumeration * reachables -- returns all objects reachable from a given object * livepaths -- returns an array of live paths because of which an * object alive. * describeRef -- returns description for a reference from a 'from' * object to a 'to' object. */ function wrapHeapSnapshot(heap) { function getClazz(clazz) { if (clazz == undefined) clazz = "java.lang.Object"; var type = typeof(clazz); if (type == "string") { clazz = heap.findClass(clazz); } else if (type == "object") { clazz = unwrapJavaObject(clazz); } else { throw "class expected";; } return clazz; } // return heap as a script object with useful methods. return { snapshot: heap, /** * Class iteration: Calls callback function for each * Java Class in the heap. Default callback function * is 'print'. If callback returns true, the iteration * is stopped. * * @param callback function to be called. */ forEachClass: function(callback) { if (callback == undefined) callback = print; var classes = this.snapshot.classes; while (classes.hasMoreElements()) { if (callback(wrapJavaValue(classes.nextElement()))) return; } },