blob: 52e0412adf31a9546a7a0713ce501666f17441da [file] [log] [blame]
/*
* Copyright (c) 2004, 2007, 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.
*
* 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.
*
*/
package sun.jvm.hotspot.utilities.soql;
import java.util.*;
import javax.script.ScriptException;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.utilities.*;
import java.lang.reflect.Method;
public class JSJavaHeap extends DefaultScriptObject {
private static final int FIELD_CAPACITY = 0;
private static final int FIELD_USED = 1;
private static final int FIELD_FOR_EACH_OBJECT = 2;
private static final int FIELD_FOR_EACH_CLASS = 3;
private static final int FIELD_UNDEFINED = -1;
public JSJavaHeap(JSJavaFactory fac) {
this.factory = fac;
}
public Object get(String name) {
int fieldID = getFieldID(name);
switch (fieldID) {
case FIELD_CAPACITY:
return new Long(getCapacity());
case FIELD_USED:
return new Long(getUsed());
case FIELD_FOR_EACH_OBJECT:
return new MethodCallable(this, forEachObjectMethod);
case FIELD_FOR_EACH_CLASS:
return new MethodCallable(this, forEachClassMethod);
case FIELD_UNDEFINED:
default:
return super.get(name);
}
}
public Object[] getIds() {
Object[] superIds = super.getIds();
Object[] tmp = fields.keySet().toArray();
Object[] res = new Object[superIds.length + tmp.length];
System.arraycopy(tmp, 0, res, 0, tmp.length);
System.arraycopy(superIds, 0, res, tmp.length, superIds.length);
return res;
}
public boolean has(String name) {
if (getFieldID(name) != FIELD_UNDEFINED) {
return true;
} else {
return super.has(name);
}
}
public void put(String name, Object value) {
if (getFieldID(name) == FIELD_UNDEFINED) {
super.put(name, value);
}
}
public void forEachObject(Object[] args) {
boolean subtypes = true;
Klass kls = null;
Callable func = null;
switch (args.length) {
case 3: {
Object b = args[2];
if (b != null && b instanceof Boolean) {
subtypes = ((Boolean)b).booleanValue();
}
}
case 2: {
Object k = args[1];
if (k == null) return;
if (k instanceof JSJavaKlass) {
kls = ((JSJavaKlass)k).getKlass();
} else if (k instanceof String) {
kls = SystemDictionaryHelper.findInstanceKlass((String)k);
if (kls == null) return;
}
}
case 1: {
Object f = args[0];
if (f != null && f instanceof Callable) {
func = (Callable) f;
} else {
// unknown target - just return
return ;
}
}
break;
default:
return;
}
final Callable finalFunc = func;
HeapVisitor visitor = new DefaultHeapVisitor() {
public boolean doObj(Oop oop) {
JSJavaObject jo = factory.newJSJavaObject(oop);
if (jo != null) {
try {
finalFunc.call(new Object[] { jo });
} catch (ScriptException exp) {
throw new RuntimeException(exp);
}
}
return false;
}
};
ObjectHeap heap = VM.getVM().getObjectHeap();
if (kls == null) {
kls = SystemDictionaryHelper.findInstanceKlass("java.lang.Object");
}
heap.iterateObjectsOfKlass(visitor, kls, subtypes);
}
public void forEachClass(Object[] args) {
boolean withLoader = false;
Callable func = null;
switch (args.length) {
case 2: {
Object b = args[1];
if (b instanceof Boolean) {
withLoader = ((Boolean)b).booleanValue();
}
}
case 1: {
Object f = args[0];
if (f instanceof Callable) {
func = (Callable) f;
} else {
return;
}
}
break;
default:
return;
}
final Callable finalFunc = func;
SystemDictionary sysDict = VM.getVM().getSystemDictionary();
if (withLoader) {
sysDict.classesDo(new SystemDictionary.ClassAndLoaderVisitor() {
public void visit(Klass kls, Oop loader) {
JSJavaKlass jk = factory.newJSJavaKlass(kls);
if (jk == null) {
return;
}
JSJavaObject k = jk.getJSJavaClass();
JSJavaObject l = factory.newJSJavaObject(loader);
if (k != null) {
if (k != null) {
try {
finalFunc.call(new Object[] { k, l });
} catch (ScriptException exp) {
throw new RuntimeException(exp);
}
}
}
}
});
} else {
sysDict.classesDo(new SystemDictionary.ClassVisitor() {
public void visit(Klass kls) {
JSJavaKlass jk = factory.newJSJavaKlass(kls);
if (jk == null) {
return;
}
JSJavaClass k = jk.getJSJavaClass();
if (k != null) {
if (k != null) {
try {
finalFunc.call(new Object[] { k });
} catch (ScriptException exp) {
throw new RuntimeException(exp);
}
}
}
}
});
}
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("Java Heap (capacity=");
buf.append(getCapacity());
buf.append(", used=");
buf.append(getUsed());
buf.append(")");
return buf.toString();
}
//-- Internals only below this point
private static Map fields = new HashMap();
private static void addField(String name, int fieldId) {
fields.put(name, new Integer(fieldId));
}
private static int getFieldID(String name) {
Integer res = (Integer) fields.get(name);
return (res != null)? res.intValue() : FIELD_UNDEFINED;
}
static {
addField("capacity", FIELD_CAPACITY);
addField("used", FIELD_USED);
addField("forEachObject", FIELD_FOR_EACH_OBJECT);
addField("forEachClass", FIELD_FOR_EACH_CLASS);
try {
Class myClass = JSJavaHeap.class;
forEachObjectMethod = myClass.getMethod("forEachObject",
new Class[] { Object[].class });
forEachClassMethod = myClass.getMethod("forEachClass",
new Class[] {Object[].class });
} catch (RuntimeException re) {
throw re;
} catch (Exception exp) {
throw new RuntimeException(exp);
}
}
private long getCapacity() {
return VM.getVM().getUniverse().heap().capacity();
}
private long getUsed() {
return VM.getVM().getUniverse().heap().used();
}
private final JSJavaFactory factory;
private static Method forEachObjectMethod;
private static Method forEachClassMethod;
}