1 /* 2 * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 package sun.jvm.hotspot.utilities.soql; 26 27 import java.util.*; 28 import javax.script.ScriptException; 29 import sun.jvm.hotspot.debugger.*; 30 import sun.jvm.hotspot.memory.*; 31 import sun.jvm.hotspot.oops.*; 32 import sun.jvm.hotspot.runtime.*; 33 import sun.jvm.hotspot.utilities.*; 34 import java.lang.reflect.Method; 35 36 public class JSJavaHeap extends DefaultScriptObject { 37 private static final int FIELD_CAPACITY = 0; 38 private static final int FIELD_USED = 1; 39 private static final int FIELD_FOR_EACH_OBJECT = 2; 40 private static final int FIELD_FOR_EACH_CLASS = 3; 41 42 private static final int FIELD_UNDEFINED = -1; 43 44 public JSJavaHeap(JSJavaFactory fac) { 45 this.factory = fac; 46 } 47 48 public Object get(String name) { 49 int fieldID = getFieldID(name); 50 switch (fieldID) { 51 case FIELD_CAPACITY: 52 return new Long(getCapacity()); 53 case FIELD_USED: 54 return new Long(getUsed()); 55 case FIELD_FOR_EACH_OBJECT: 56 return new MethodCallable(this, forEachObjectMethod); 57 case FIELD_FOR_EACH_CLASS: 58 return new MethodCallable(this, forEachClassMethod); 59 case FIELD_UNDEFINED: 60 default: 61 return super.get(name); 62 } 63 } 64 65 public Object[] getIds() { 66 Object[] superIds = super.getIds(); 67 Object[] tmp = fields.keySet().toArray(); 68 Object[] res = new Object[superIds.length + tmp.length]; 69 System.arraycopy(tmp, 0, res, 0, tmp.length); 70 System.arraycopy(superIds, 0, res, tmp.length, superIds.length); 71 return res; 72 } 73 74 public boolean has(String name) { 75 if (getFieldID(name) != FIELD_UNDEFINED) { 76 return true; 77 } else { 78 return super.has(name); 79 } 80 } 81 82 public void put(String name, Object value) { 83 if (getFieldID(name) == FIELD_UNDEFINED) { 84 super.put(name, value); 85 } 86 } 87 88 public void forEachObject(Object[] args) { 89 boolean subtypes = true; 90 Klass kls = null; 91 Callable func = null; 92 switch (args.length) { 93 case 3: { 94 Object b = args[2]; 95 if (b != null && b instanceof Boolean) { 96 subtypes = ((Boolean)b).booleanValue(); 97 } 98 } 99 case 2: { 100 Object k = args[1]; 101 if (k == null) return; 102 if (k instanceof JSJavaKlass) { 103 kls = ((JSJavaKlass)k).getKlass(); 104 } else if (k instanceof String) { 105 kls = SystemDictionaryHelper.findInstanceKlass((String)k); 106 if (kls == null) return; 107 } 108 } 109 case 1: { 110 Object f = args[0]; 111 if (f != null && f instanceof Callable) { 112 func = (Callable) f; 113 } else { 114 // unknown target - just return 115 return ; 116 } 117 } 118 break; 119 120 default: 121 return; 122 } 123 124 final Callable finalFunc = func; 125 HeapVisitor visitor = new DefaultHeapVisitor() { 126 public boolean doObj(Oop oop) { 127 JSJavaObject jo = factory.newJSJavaObject(oop); 128 if (jo != null) { 129 try { 130 finalFunc.call(new Object[] { jo }); 131 } catch (ScriptException exp) { 132 throw new RuntimeException(exp); 133 } 134 } 135 return false; 136 } 137 }; 138 ObjectHeap heap = VM.getVM().getObjectHeap(); 139 if (kls == null) { 140 kls = SystemDictionaryHelper.findInstanceKlass("java.lang.Object"); 141 } 142 heap.iterateObjectsOfKlass(visitor, kls, subtypes); 143 } 144 145 public void forEachClass(Object[] args) { 146 boolean withLoader = false; 147 Callable func = null; 148 switch (args.length) { 149 case 2: { 150 Object b = args[1]; 151 if (b instanceof Boolean) { 152 withLoader = ((Boolean)b).booleanValue(); 153 } 154 } 155 case 1: { 156 Object f = args[0]; 157 if (f instanceof Callable) { 158 func = (Callable) f; 159 } else { 160 return; 161 } 162 } 163 break; 164 default: 165 return; 166 } 167 168 final Callable finalFunc = func; 169 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); 170 if (withLoader) { 171 sysDict.classesDo(new SystemDictionary.ClassAndLoaderVisitor() { 172 public void visit(Klass kls, Oop loader) { 173 JSJavaKlass jk = factory.newJSJavaKlass(kls); 174 if (jk == null) { 175 return; 176 } 177 JSJavaObject k = jk.getJSJavaClass(); 178 JSJavaObject l = factory.newJSJavaObject(loader); 179 if (k != null) { 180 if (l != null) { 181 try { 182 finalFunc.call(new Object[] { k, l }); 183 } catch (ScriptException exp) { 184 throw new RuntimeException(exp); 185 } 186 } 187 } 188 } 189 }); 190 191 } else { 192 sysDict.classesDo(new SystemDictionary.ClassVisitor() { 193 public void visit(Klass kls) { 194 JSJavaKlass jk = factory.newJSJavaKlass(kls); 195 if (jk == null) { 196 return; 197 } 198 JSJavaClass k = jk.getJSJavaClass(); 199 if (k != null) { 200 if (k != null) { 201 try { 202 finalFunc.call(new Object[] { k }); 203 } catch (ScriptException exp) { 204 throw new RuntimeException(exp); 205 } 206 } 207 } 208 } 209 }); 210 } 211 } 212 213 public String toString() { 214 StringBuffer buf = new StringBuffer(); 215 buf.append("Java Heap (capacity="); 216 buf.append(getCapacity()); 217 buf.append(", used="); 218 buf.append(getUsed()); 219 buf.append(")"); 220 return buf.toString(); 221 } 222 223 //-- Internals only below this point 224 private static Map fields = new HashMap(); 225 private static void addField(String name, int fieldId) { 226 fields.put(name, new Integer(fieldId)); 227 } 228 229 private static int getFieldID(String name) { 230 Integer res = (Integer) fields.get(name); 231 return (res != null)? res.intValue() : FIELD_UNDEFINED; 232 } 233 234 static { 235 addField("capacity", FIELD_CAPACITY); 236 addField("used", FIELD_USED); 237 addField("forEachObject", FIELD_FOR_EACH_OBJECT); 238 addField("forEachClass", FIELD_FOR_EACH_CLASS); 239 try { 240 Class myClass = JSJavaHeap.class; 241 forEachObjectMethod = myClass.getMethod("forEachObject", 242 new Class[] { Object[].class }); 243 forEachClassMethod = myClass.getMethod("forEachClass", 244 new Class[] {Object[].class }); 245 } catch (RuntimeException re) { 246 throw re; 247 } catch (Exception exp) { 248 throw new RuntimeException(exp); 249 } 250 } 251 252 private long getCapacity() { 253 return VM.getVM().getUniverse().heap().capacity(); 254 } 255 256 private long getUsed() { 257 return VM.getVM().getUniverse().heap().used(); 258 } 259 260 private final JSJavaFactory factory; 261 private static Method forEachObjectMethod; 262 private static Method forEachClassMethod; 263 }