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.classfile.*; 31 import sun.jvm.hotspot.memory.*; 32 import sun.jvm.hotspot.oops.*; 33 import sun.jvm.hotspot.runtime.*; 34 import sun.jvm.hotspot.utilities.*; 35 import java.lang.reflect.Method; 36 37 public class JSJavaHeap extends DefaultScriptObject { 38 private static final int FIELD_CAPACITY = 0; 39 private static final int FIELD_USED = 1; 40 private static final int FIELD_FOR_EACH_OBJECT = 2; 41 private static final int FIELD_FOR_EACH_CLASS = 3; 42 43 private static final int FIELD_UNDEFINED = -1; 44 45 public JSJavaHeap(JSJavaFactory fac) { 46 this.factory = fac; 47 } 48 49 public Object get(String name) { 50 int fieldID = getFieldID(name); 51 switch (fieldID) { 52 case FIELD_CAPACITY: 53 return new Long(getCapacity()); 54 case FIELD_USED: 55 return new Long(getUsed()); 56 case FIELD_FOR_EACH_OBJECT: 57 return new MethodCallable(this, forEachObjectMethod); 58 case FIELD_FOR_EACH_CLASS: 59 return new MethodCallable(this, forEachClassMethod); 60 case FIELD_UNDEFINED: 61 default: 62 return super.get(name); 63 } 64 } 65 66 public Object[] getIds() { 67 Object[] superIds = super.getIds(); 68 Object[] tmp = fields.keySet().toArray(); 69 Object[] res = new Object[superIds.length + tmp.length]; 70 System.arraycopy(tmp, 0, res, 0, tmp.length); 71 System.arraycopy(superIds, 0, res, tmp.length, superIds.length); 72 return res; 73 } 74 75 public boolean has(String name) { 76 if (getFieldID(name) != FIELD_UNDEFINED) { 77 return true; 78 } else { 79 return super.has(name); 80 } 81 } 82 83 public void put(String name, Object value) { 84 if (getFieldID(name) == FIELD_UNDEFINED) { 85 super.put(name, value); 86 } 87 } 88 89 public void forEachObject(Object[] args) { 90 boolean subtypes = true; 91 Klass kls = null; 92 Callable func = null; 93 switch (args.length) { 94 case 3: { 95 Object b = args[2]; 96 if (b != null && b instanceof Boolean) { 97 subtypes = ((Boolean)b).booleanValue(); 98 } 99 } 100 case 2: { 101 Object k = args[1]; 102 if (k == null) return; 103 if (k instanceof JSJavaKlass) { 104 kls = ((JSJavaKlass)k).getKlass(); 105 } else if (k instanceof String) { 106 kls = SystemDictionaryHelper.findInstanceKlass((String)k); 107 if (kls == null) return; 108 } 109 } 110 case 1: { 111 Object f = args[0]; 112 if (f != null && f instanceof Callable) { 113 func = (Callable) f; 114 } else { 115 // unknown target - just return 116 return ; 117 } 118 } 119 break; 120 121 default: 122 return; 123 } 124 125 final Callable finalFunc = func; 126 HeapVisitor visitor = new DefaultHeapVisitor() { 127 public boolean doObj(Oop oop) { 128 JSJavaObject jo = factory.newJSJavaObject(oop); 129 if (jo != null) { 130 try { 131 finalFunc.call(new Object[] { jo }); 132 } catch (ScriptException exp) { 133 throw new RuntimeException(exp); 134 } 135 } 136 return false; 137 } 138 }; 139 ObjectHeap heap = VM.getVM().getObjectHeap(); 140 if (kls == null) { 141 kls = SystemDictionaryHelper.findInstanceKlass("java.lang.Object"); 142 } 143 heap.iterateObjectsOfKlass(visitor, kls, subtypes); 144 } 145 146 public void forEachClass(Object[] args) { 147 boolean withLoader = false; 148 Callable func = null; 149 switch (args.length) { 150 case 2: { 151 Object b = args[1]; 152 if (b instanceof Boolean) { 153 withLoader = ((Boolean)b).booleanValue(); 154 } 155 } 156 case 1: { 157 Object f = args[0]; 158 if (f instanceof Callable) { 159 func = (Callable) f; 160 } else { 161 return; 162 } 163 } 164 break; 165 default: 166 return; 167 } 168 169 final Callable finalFunc = func; 170 ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph(); 171 if (withLoader) { 172 cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() { 173 public void visit(Klass kls) { 174 JSJavaKlass jk = factory.newJSJavaKlass(kls); 175 Oop loader = kls.getClassLoader(); 176 if (jk == null) { 177 return; 178 } 179 JSJavaObject k = jk.getJSJavaClass(); 180 JSJavaObject l = factory.newJSJavaObject(loader); 181 if (k != null) { 182 if (l != null) { 183 try { 184 finalFunc.call(new Object[] { k, l }); 185 } catch (ScriptException exp) { 186 throw new RuntimeException(exp); 187 } 188 } 189 } 190 } 191 }); 192 193 } else { 194 cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() { 195 public void visit(Klass kls) { 196 JSJavaKlass jk = factory.newJSJavaKlass(kls); 197 if (jk == null) { 198 return; 199 } 200 JSJavaClass k = jk.getJSJavaClass(); 201 if (k != null) { 202 if (k != null) { 203 try { 204 finalFunc.call(new Object[] { k }); 205 } catch (ScriptException exp) { 206 throw new RuntimeException(exp); 207 } 208 } 209 } 210 } 211 }); 212 } 213 } 214 215 public String toString() { 216 StringBuffer buf = new StringBuffer(); 217 buf.append("Java Heap (capacity="); 218 buf.append(getCapacity()); 219 buf.append(", used="); 220 buf.append(getUsed()); 221 buf.append(")"); 222 return buf.toString(); 223 } 224 225 //-- Internals only below this point 226 private static Map fields = new HashMap(); 227 private static void addField(String name, int fieldId) { 228 fields.put(name, new Integer(fieldId)); 229 } 230 231 private static int getFieldID(String name) { 232 Integer res = (Integer) fields.get(name); 233 return (res != null)? res.intValue() : FIELD_UNDEFINED; 234 } 235 236 static { 237 addField("capacity", FIELD_CAPACITY); 238 addField("used", FIELD_USED); 239 addField("forEachObject", FIELD_FOR_EACH_OBJECT); 240 addField("forEachClass", FIELD_FOR_EACH_CLASS); 241 try { 242 Class myClass = JSJavaHeap.class; 243 forEachObjectMethod = myClass.getMethod("forEachObject", 244 new Class[] { Object[].class }); 245 forEachClassMethod = myClass.getMethod("forEachClass", 246 new Class[] {Object[].class }); 247 } catch (RuntimeException re) { 248 throw re; 249 } catch (Exception exp) { 250 throw new RuntimeException(exp); 251 } 252 } 253 254 private long getCapacity() { 255 return VM.getVM().getUniverse().heap().capacity(); 256 } 257 258 private long getUsed() { 259 return VM.getVM().getUniverse().heap().used(); 260 } 261 262 private final JSJavaFactory factory; 263 private static Method forEachObjectMethod; 264 private static Method forEachClassMethod; 265 }