| /* |
| * Copyright (c) 2004, 2017, 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.classfile.*; |
| 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; |
| ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph(); |
| if (withLoader) { |
| cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() { |
| public void visit(Klass kls) { |
| JSJavaKlass jk = factory.newJSJavaKlass(kls); |
| Oop loader = kls.getClassLoader(); |
| if (jk == null) { |
| return; |
| } |
| JSJavaObject k = jk.getJSJavaClass(); |
| JSJavaObject l = factory.newJSJavaObject(loader); |
| if (k != null) { |
| if (l != null) { |
| try { |
| finalFunc.call(new Object[] { k, l }); |
| } catch (ScriptException exp) { |
| throw new RuntimeException(exp); |
| } |
| } |
| } |
| } |
| }); |
| |
| } else { |
| cldg.classesDo(new ClassLoaderDataGraph.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; |
| } |