001: /*
002: * Distributable under LGPL license. See terms of license at gnu.org.
003: */
004:
005: package org.jboss.profiler.jvmtitest;
006:
007: import java.io.File;
008: import java.io.IOException;
009: import java.lang.reflect.Field;
010: import java.util.ArrayList;
011: import java.util.Collection;
012: import java.util.HashMap;
013: import java.util.Iterator;
014: import java.util.Map;
015: import java.util.WeakHashMap;
016:
017: import junit.framework.TestCase;
018:
019: import org.jboss.profiler.jvmti.InventoryDataPoint;
020: import org.jboss.profiler.jvmti.JVMTICallBack;
021: import org.jboss.profiler.jvmti.JVMTIInterface;
022: import org.jboss.profiler.jvmti.ReferenceDataPoint;
023: import org.jboss.profiler.memoryprofiler.engine.MemorySnapshotController;
024: import org.jboss.profiler.memoryprofiler.engine.MemorySnapshotEngine;
025: import org.jboss.profiler.memoryprofiler.model.MemoryClass;
026:
027: class B {
028: }
029:
030: class Dummy {
031: String a;
032: String b;
033: B b12 = null;
034: String c;
035: static B staticB;
036: }
037:
038: class A extends Dummy {
039: public A() {
040: b = new B();
041: staticB = b;
042: }
043:
044: B b;
045: B b1 = null;
046: String str = null;
047: }
048:
049: class Holder {
050: int count = 0;
051:
052: UsedByHolder[] objs = new UsedByHolder[100000];
053:
054: public void addInstance(UsedByHolder obj) {
055: objs[count++] = obj;
056:
057: }
058:
059: public void print() {
060: for (int i = 0; i < count; i++) {
061: System.out.println("class=" + objs[i].toString());
062: }
063:
064: }
065: }
066:
067: class UsedByHolder {
068: int x;
069:
070: static int count = 0;
071:
072: public UsedByHolder() {
073: x = count++;
074: }
075:
076: public String toString() {
077: return "value " + x;
078: }
079: }
080:
081: /**
082: * To run this test, you need to use -agentlib:jbossAgent in you IDE
083: * @author Clebert Suconic
084: */
085:
086: public class JVMTITest extends TestCase {
087: static class LocalCallbackTestOnClasses implements JVMTICallBack {
088: int count = 0;
089:
090: public void notifyReference(long referenceHolder,
091: long referencedObject, long classTag, long index,
092: long method, byte referenceType) {
093: fail("Shouldn't be called");
094: }
095:
096: public void notifyClass(long classTag, Class clazz) {
097: count++;
098: }
099:
100: public void notifyObject(long classTag, long objectId,
101: long bytes) {
102: fail("Shouldn't be called");
103:
104: }
105: }
106:
107: static class LocalCallbackTestOnObjects implements JVMTICallBack {
108: int count = 0;
109:
110: public void notifyReference(long referenceHolder,
111: long referencedObject, long classTag, long index,
112: long method, byte referenceType) {
113: fail("Shouldn't be called");
114: }
115:
116: public void notifyClass(long classTag, Class clazz) {
117: fail("Shouldn't be called");
118: }
119:
120: public void notifyObject(long classTag, long objectId,
121: long bytes) {
122: count++;
123: }
124: }
125:
126: public void testNotifyOnClasses() {
127: JVMTIInterface jvmti = new JVMTIInterface();
128: LocalCallbackTestOnClasses localTest = new LocalCallbackTestOnClasses();
129: jvmti.notifyInventory(true, null, null, localTest);
130:
131: assertEquals(jvmti.getLoadedClasses().length, localTest.count);
132: }
133:
134: public void testInventoryReport() throws Exception {
135: JVMTIInterface jvmti = new JVMTIInterface();
136: System.out.println(jvmti.inventoryReport());
137: }
138:
139: public void testProduceInventoryMinimal() throws Exception {
140: JVMTIInterface jvmti = new JVMTIInterface(); // The JVMTIWrapper used to produce inventories
141:
142: Map map = jvmti.produceInventory();
143: Map map2 = jvmti.produceInventory();
144: assertTrue(jvmti.compareInventories(System.out, map, map2,
145: null, null, null));
146:
147: }
148:
149: public void testProduceInventory() throws Exception {
150: class TestClass {
151:
152: }
153:
154: JVMTIInterface jvmti = new JVMTIInterface(); // The JVMTIWrapper used to produce inventories
155:
156: Map map = jvmti.produceInventory();
157: Map map2 = jvmti.produceInventory();
158: jvmti.compareInventories(System.out, map, map2, null, null,
159: null);
160: System.out.println("size=" + map.size());
161: map = null;
162: map2 = null;
163:
164: TestClass keepr = new TestClass(); // at least one instance, so point2 won't be null
165:
166: Map firstMap = jvmti.produceInventory(); // The inventory of classes, this is HashMap<Class,InventoryDataPoint>
167:
168: TestClass[] tests = new TestClass[1000];
169: for (int i = 0; i < 1000; i++) {
170: tests[i] = new TestClass(); // allocating 1000 objects
171: }
172:
173: Map secondMap = jvmti.produceInventory(); // the second inventory
174:
175: InventoryDataPoint point1 = (InventoryDataPoint) secondMap
176: .get(TestClass.class);
177: InventoryDataPoint point2 = (InventoryDataPoint) firstMap
178: .get(TestClass.class);
179:
180: assertEquals(1000, point1.getInstances()
181: - point2.getInstances()); // you can manually compare it
182:
183: assertTrue(jvmti.compareInventories(System.out, firstMap,
184: secondMap, new Class[] { WeakHashMap.class },
185: new String[] { "[Ljava.util.WeakHashMap$Entry;",
186: "java.lang.ref" },
187: new InventoryDataPoint[] { new InventoryDataPoint(
188: TestClass.class, 2000) }));
189: assertFalse(jvmti.compareInventories(System.out, firstMap,
190: secondMap, new Class[] { WeakHashMap.class },
191: new String[] { "[Ljava.util.WeakHashMap$Entry;",
192: "java.lang.ref" },
193: new InventoryDataPoint[] { new InventoryDataPoint(
194: TestClass.class, 100) }));
195:
196: }
197:
198: public void testExploreObject() throws Exception {
199: A a = new A();
200: B b = a.b;
201:
202: JVMTIInterface jvmti = new JVMTIInterface();
203: HashMap map = jvmti.createIndexMatrix();
204: jvmti.exploreClassReferences(B.class.getName(), -1, true, true,
205: true, true, false, map);
206:
207: System.out.println(jvmti.exploreObjectReferences(map, b, 1,
208: true));
209: /*map=null;
210: jvmti.releaseTags();
211: System.out.println(jvmti.exploreObjectReferences(B.class.getName(),2,true)); */
212:
213: }
214:
215: public void notestNotify() {
216: A a = new A();
217: B b = a.b;
218: final ArrayList list = new ArrayList();
219:
220: JVMTIInterface jvmti = new JVMTIInterface();
221: jvmti.notifyOnReferences("/tmp/tst.refs", new JVMTICallBack() {
222:
223: int count = 0;
224:
225: public void notifyReference(long referenceHolder,
226: long referencedObject, long classTag, long index,
227: long method, byte referenceType) {
228: list.add(new ReferenceDataPoint(referenceHolder,
229: referencedObject, classTag, index, method,
230: referenceType));
231: }
232:
233: public void notifyClass(long classTag, Class clazz) {
234: fail("This shouldn't be called now");
235: }
236:
237: public void notifyObject(long classTag, long objectId,
238: long bytes) {
239: fail("This shouldn't be called now");
240: }
241: });
242:
243: long tag = jvmti.getTagOnObject(a);
244: Object newObject = jvmti.getObjectOnTag(tag);
245: assertSame(a, newObject);
246:
247: int count = 0;
248: Iterator iter = list.iterator();
249: while (iter.hasNext()) {
250: ReferenceDataPoint point = (ReferenceDataPoint) iter.next();
251: //System.out.println("point=" + point);
252: if (point.getClassTag() != 0) {
253: Object obj = jvmti.getObjectOnTag(point.getClassTag());
254: if (!(obj instanceof Class)) {
255: System.out.println("point=" + point);
256: System.out.println("obj=" + obj);
257: fail("Object was supposed to be a Class");
258: }
259: }
260:
261: if (point.getReferenceType() == JVMTICallBack.JVMTI_REFERENCE_STATIC_FIELD
262: || point.getReferenceType() == JVMTICallBack.JVMTI_REFERENCE_FIELD) {
263: try {
264:
265: Object referenced = jvmti.getObjectOnTag(point
266: .getReferencedObject());
267: Object obj = jvmti.getObjectOnTag(point
268: .getReferenceHolder());
269: Field field = jvmti.getObjectField(obj.getClass(),
270: (int) point.getIndex());
271: Class clazz = (Class) jvmti.getObjectOnTag(point
272: .getClassTag());
273: /*if (field==null)
274: {
275: System.out.println(point);
276: System.out.println(referenced + " couldn't find field " +point.getIndex() + " on " + obj);
277: Field field2 = jvmti.getObjectField(obj .getClass(),(int)point.getIndex());
278: }
279: assertNotNull(field); -- I would like to enforce this, but it seems impossible due to internal classes on JVM */
280: } catch (NullPointerException e) {
281: }
282: } else if (point.getReferenceType() == JVMTICallBack.THREAD_REFERENCE) {
283: try {
284: Object classTag = jvmti.getObjectOnTag(point
285: .getClassTag());
286: Object objReferenced = jvmti.getObjectOnTag(point
287: .getReferencedObject());
288: Object objHolder = jvmti.getObjectOnTag(point
289: .getReferenceHolder());
290:
291: String methodName = jvmti.getMethodClass(
292: point.getMethod()).getName()
293: + "::"
294: + jvmti.getMethodName(point.getMethod())
295: + jvmti.getMethodSignature(point
296: .getMethod());
297: //System.out.println(objReferenced + " being referenced at "+methodName);
298: } catch (NullPointerException e) {
299: // this can happen here;
300: }
301: }
302:
303: }
304:
305: System.out.println();
306:
307: long tagOnA = jvmti.getTagOnObject(a.b);
308: iter = list.iterator();
309: while (iter.hasNext()) {
310: ReferenceDataPoint point = (ReferenceDataPoint) iter.next();
311:
312: if (tagOnA == point.getReferencedObject()
313: && (point.getReferenceType() == JVMTICallBack.JVMTI_REFERENCE_FIELD || point
314: .getReferenceType() == JVMTICallBack.JVMTI_REFERENCE_STATIC_FIELD)) {
315: Object obj = jvmti.getObjectOnTag(point
316: .getReferenceHolder());
317: Field field = null;
318:
319: if (point.getReferenceType() == JVMTICallBack.JVMTI_REFERENCE_FIELD) {
320: field = jvmti.getObjectField(
321: (Class) obj.getClass(), (int) point
322: .getIndex());
323: } else {
324: field = jvmti.getObjectField((Class) obj,
325: (int) point.getIndex());
326: }
327: System.out.println(obj + " being referenced at "
328: + field);
329: } else if (tagOnA == point.getReferencedObject()
330: && (point.getReferenceType() == JVMTICallBack.THREAD_REFERENCE)) {
331: Object classTag = jvmti.getObjectOnTag(point
332: .getClassTag());
333: Object objReferenced = jvmti.getObjectOnTag(point
334: .getReferencedObject());
335: Object objHolder = jvmti.getObjectOnTag(point
336: .getReferenceHolder());
337:
338: System.out.println("classTag=" + classTag);
339: System.out.println("objReferenced=" + objReferenced);
340: System.out.println("objHolder=" + objHolder);
341: System.out.println("name="
342: + jvmti.getMethodClass(point.getMethod())
343: .getName() + "::"
344: + jvmti.getMethodName(point.getMethod())
345: + jvmti.getMethodSignature(point.getMethod()));
346: }
347: }
348:
349: try {
350: jvmti.getObjectOnTag(0);
351: fail("Supposed to throw an exception");
352: } catch (Throwable e) {
353: }
354:
355: try {
356: jvmti.getObjectOnTag(-1);
357: fail("Supposed to throw an exception");
358: } catch (Throwable e) {
359: }
360:
361: jvmti.releaseTags();
362: assertEquals(0, jvmti.getTagOnObject(a));
363:
364: }
365:
366: public void testGetReferenceHolders() {
367: JVMTIInterface jvmti = new JVMTIInterface();
368: A a = new A();
369: Object[] objects = jvmti
370: .getReferenceHolders(new Object[] { a.b });
371: assertEquals(2, objects.length);
372: assertSame(a, objects[0]);
373: }
374:
375: public void testGetObjects() {
376: JVMTIInterface interfaceJVMTI = new JVMTIInterface();
377: Object[] result = interfaceJVMTI
378: .getAllObjects(java.lang.String.class);
379:
380: for (int i = 0; i < result.length; i++) {
381: System.out.println("String result[" + i + "]=" + result[i]);
382: }
383:
384: result = interfaceJVMTI.getAllObjects(java.lang.Class.class);
385: assertTrue(result.length > 0);
386:
387: for (int i = 0; i < result.length; i++) {
388: System.out.println("class result[" + i + "]=" + result[i]);
389: }
390: }
391:
392: ThreadLocal local = new ThreadLocal();
393:
394: static Holder holder[] = new Holder[100];
395:
396: static {
397: for (int i = 0; i < holder.length; i++) {
398: holder[i] = new Holder();
399: }
400: }
401:
402: public void testHolders() throws Exception {
403: JVMTIInterface interfaceJVMTI = new JVMTIInterface();
404:
405: Object holders[] = interfaceJVMTI
406: .getReferenceHolders(new Object[] { this });
407:
408: System.out.println("There are " + holders.length
409: + " holding a reference");
410: }
411:
412: public void testNavigation() throws Exception {
413: JVMTIInterface interfaceJVMTI = new JVMTIInterface();
414: Class classes[] = interfaceJVMTI.getLoadedClasses();
415: System.out.println("length=" + classes.length);
416: ArrayList stringVer = new ArrayList();
417: stringVer.add(new String("tst"));
418: try {
419: Thread.sleep(1000);
420: } catch (Exception e) {
421: e.printStackTrace();
422: }
423:
424: Holder holder = new Holder();
425: holder.addInstance(new UsedByHolder());
426: holder.addInstance(new UsedByHolder());
427:
428: Holder holder2 = new Holder();
429: holder2.addInstance(new UsedByHolder());
430: holder2.addInstance(new UsedByHolder());
431:
432: Holder holder3 = new Holder();
433: holder3 = null;
434:
435: local.set(holder3);
436:
437: JVMTIInterface jvmti = new JVMTIInterface();
438: jvmti.forceGC();
439:
440: //File tmpFile = File.createTempFile("profiler","");
441: File tmpFile = new File("tst", "");
442:
443: System.out.println("Generating data to "
444: + tmpFile.getAbsolutePath());
445:
446: jvmti.heapSnapshot(tmpFile.getAbsolutePath(), "log");
447: holder.print();
448: holder2.print();
449:
450: MemorySnapshotEngine engine = new MemorySnapshotEngine();
451: engine.processFiles(tmpFile.getAbsolutePath(), "log");
452:
453: MemorySnapshotController controller = new MemorySnapshotController(
454: engine);
455: Collection coll = controller.filterRoots(false);
456:
457: Iterator iter = coll.iterator();
458:
459: int i = 0;
460: while (iter.hasNext()) {
461: MemoryClass clazz = (MemoryClass) iter.next();
462: if ((i++) == 1) {
463: Collection collResult = controller
464: .summarizeReferenceByPath(true,
465: new String[] { "C" + clazz.getId() });
466: //assertTrue(collResult.size()>0);
467: }
468:
469: if (clazz.getClassLoaderId() != 0) {
470: Collection collClassLoader = controller
471: .solveLoadedClass(clazz.getClassLoaderId(),
472: false);
473: }
474:
475: }
476:
477: }
478:
479: public static void main(String arg[]) {
480: JVMTITest test = new JVMTITest();
481:
482: try {
483: test.testGetObjects();
484: } catch (Throwable e1) {
485: e1.printStackTrace();
486: }
487:
488: try {
489: test.testNavigation();
490: } catch (Throwable e) {
491: e.printStackTrace();
492: }
493: }
494: }
|