Source Code Cross Referenced for JVMTIInterface.java in  » Profiler » jboss-profiler » org » jboss » profiler » jvmti » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Profiler » jboss profiler » org.jboss.profiler.jvmti 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * JBoss, Home of Professional Open Source
0003:         * Copyright 2005, JBoss Inc., and individual contributors as indicated
0004:         * by the @authors tag. See the copyright.txt in the distribution for a
0005:         * full listing of individual contributors.
0006:         *
0007:         * This is free software; you can redistribute it and/or modify it
0008:         * under the terms of the GNU Lesser General Public License as
0009:         * published by the Free Software Foundation; either version 2.1 of
0010:         * the License, or (at your option) any later version.
0011:         *
0012:         * This software is distributed in the hope that it will be useful,
0013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0015:         * Lesser General Public License for more details.
0016:         *
0017:         * You should have received a copy of the GNU Lesser General Public
0018:         * License along with this software; if not, write to the Free
0019:         * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020:         * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
0021:         */
0022:        package org.jboss.profiler.jvmti;
0023:
0024:        import gnu.trove.TLongObjectHashMap;
0025:
0026:        import java.io.ByteArrayInputStream;
0027:        import java.io.ByteArrayOutputStream;
0028:        import java.io.CharArrayWriter;
0029:        import java.io.File;
0030:        import java.io.IOException;
0031:        import java.io.ObjectInputStream;
0032:        import java.io.ObjectOutputStream;
0033:        import java.io.PrintStream;
0034:        import java.io.PrintWriter;
0035:        import java.io.Serializable;
0036:        import java.lang.ref.SoftReference;
0037:        import java.lang.ref.WeakReference;
0038:        import java.lang.reflect.Field;
0039:        import java.util.ArrayList;
0040:        import java.util.Collection;
0041:        import java.util.Collections;
0042:        import java.util.Comparator;
0043:        import java.util.HashMap;
0044:        import java.util.HashSet;
0045:        import java.util.Iterator;
0046:        import java.util.Map;
0047:        import java.util.TreeSet;
0048:        import java.util.WeakHashMap;
0049:
0050:        import org.jboss.logging.Logger;
0051:
0052:        /**
0053:         * @author Clebert Suconic
0054:         */
0055:        public class JVMTIInterface implements  JVMTIInterfaceMBean {
0056:            private static final Logger log = Logger
0057:                    .getLogger(JVMTIInterface.class);
0058:
0059:            private static boolean isLoaded = true;
0060:            static {
0061:                try {
0062:                    System.loadLibrary("jbossAgent");
0063:                } catch (Throwable e) {
0064:                    isLoaded = false;
0065:                    log
0066:                            .error(
0067:                                    "The DLL couldn't be loaded, you won't be able to use any JVMTIInterface feature",
0068:                                    e);
0069:                }
0070:            }
0071:
0072:            private void addTo(Collection coll, Field[] obj) {
0073:                for (int i = 0; i < obj.length; i++) {
0074:                    coll.add(obj[i]);
0075:                    obj[i].setAccessible(true);
0076:                }
0077:            }
0078:
0079:            public Field[] retrieveAllFields(Class clazz) {
0080:
0081:                ArrayList list = new ArrayList();
0082:
0083:                for (Class super Class = clazz; super Class != null; super Class = super Class
0084:                        .getSuperclass()) {
0085:                    addTo(list, super Class.getDeclaredFields());
0086:                }
0087:
0088:                return (Field[]) list.toArray(new Field[list.size()]);
0089:
0090:            }
0091:
0092:            /** Force a GC. This method doesn't use System.gc. If JVMTI is enabled this will really cause a FullGC by calling a JVMTI function. */
0093:            public native void forceGC();
0094:
0095:            /** returns the first class found with a given name */
0096:            public Class getClassByName(String className) {
0097:                Class classes[] = getLoadedClasses();
0098:
0099:                for (int i = 0; i < classes.length; i++) {
0100:                    if (classes[i].getName().equals(className)) {
0101:                        return classes[i];
0102:                    }
0103:                }
0104:
0105:                return null;
0106:            }
0107:
0108:            /** Will release internal tags used by previous methods. 
0109:             * All the navigations through JVMTI are done through tagging. Calling this method will release any tagging done by previous methods. */
0110:            public native void releaseTags();
0111:
0112:            /** This method will keep every object tagged for later usage. This method is going to tag objects. */
0113:            public native void notifyInventory(boolean notifyOnClasses,
0114:                    String temporaryFileReferences,
0115:                    String temporaryFileObjects, JVMTICallBack callback);
0116:
0117:            public void notifyOnReferences(String temporaryFile,
0118:                    JVMTICallBack callback) {
0119:                notifyInventory(false, temporaryFile, null, callback);
0120:            }
0121:
0122:            /** Will get all the objects holding references to these objects passed by parameter. This method is going to release tags, be careful if you are on the middle of navigations. */
0123:            public native Object[] getReferenceHolders(Object[] objects);
0124:
0125:            public native Class[] getLoadedClasses();
0126:
0127:            /** Will return all methods of a give class. This will change tags, be careful if you are on the middle of navitations. */
0128:            public native Object[] getAllObjects(Class clazz);
0129:
0130:            /** Will return the tag of an object */
0131:            public native long getTagOnObject(Object obj);
0132:
0133:            /** Will return the object on a tag*/
0134:            public native Object getObjectOnTag(long tag);
0135:
0136:            private native boolean internalIsConfiguredProperly();
0137:
0138:            /** Returns true if -agentlib:jbossAgent was configured properly */
0139:            public boolean isActive() {
0140:                if (!isLoaded) {
0141:                    return false;
0142:                } else {
0143:                    return internalIsConfiguredProperly();
0144:                }
0145:            }
0146:
0147:            /** Returns the field represted by the FieldId. This is used on field relationships according to the rule determined by JVMTI documentation. */
0148:            public Field getObjectField(Class clazz, int fieldId) {
0149:                ArrayList list = new ArrayList();
0150:                list.add(clazz);
0151:                while ((clazz = clazz.getSuperclass()) != null) {
0152:                    list.add(clazz);
0153:                }
0154:
0155:                for (int i = list.size() - 1; i >= 0; i--) {
0156:                    Field fields[] = ((Class) list.get(i)).getDeclaredFields();
0157:                    if (fieldId < fields.length) {
0158:                        return fields[fieldId];
0159:                    }
0160:                    fieldId -= fields.length;
0161:                }
0162:                return null;
0163:            }
0164:
0165:            public native String getMethodName(long methodId);
0166:
0167:            public native String getMethodSignature(long methodId);
0168:
0169:            public native Class getMethodClass(long methodId);
0170:
0171:            /** @deprecated use getLoadedClasses */
0172:            public Class[] retrieveLoadedClasses() {
0173:                return getLoadedClasses();
0174:            }
0175:
0176:            protected static native void heapSnapshot(String classesFileName,
0177:                    String referencesFileName, String objectsFileName);
0178:
0179:            /** Will call {@link JVMTIInterface.heapSnapshot(String,String,String)} passing "_classes, _references, _objects in the name of the files */
0180:            public void heapSnapshot(String basicFileName, String suffix) {
0181:                forceGC();
0182:                heapSnapshot(basicFileName + "_classes" + "." + suffix,
0183:                        basicFileName + "_references" + "." + suffix,
0184:                        basicFileName + "_objects" + "." + suffix);
0185:            }
0186:
0187:            /** Return every single object on a give class by its name. This method will look for every single class with this name, and if more than one classLoader is loading a class with this name, this method will return objects for all the respective classes.
0188:             *  For example if you look for a Structs Action Form, this will return every ActionForm defined on the current JVM. */
0189:            public Object[] getAllObjects(String clazz) {
0190:                ArrayList list = new ArrayList();
0191:
0192:                Class[] classes = this .getLoadedClasses();
0193:                for (int i = 0; i < classes.length; i++) {
0194:                    if (classes[i].getName().equals(clazz)) {
0195:                        Object objs[] = this .getAllObjects(classes[i]);
0196:                        for (int count = 0; count < objs.length; count++) {
0197:                            list.add(objs[count]);
0198:                        }
0199:                    }
0200:                }
0201:
0202:                return list.toArray();
0203:            }
0204:
0205:            static class ClassSorterByClassLoader implements  Comparator {
0206:
0207:                public int compare(Object o1, Object o2) {
0208:                    Class left = (Class) o1;
0209:                    Class right = (Class) o2;
0210:
0211:                    int compare = 0;
0212:
0213:                    if ((compare = compareClassLoader(left.getClassLoader(),
0214:                            right.getClassLoader())) != 0)
0215:                        return compare;
0216:
0217:                    return left.getName().compareTo(right.getName());
0218:                }
0219:
0220:                public int compareClassLoader(ClassLoader left,
0221:                        ClassLoader right) {
0222:                    if (left == null || right == null) {
0223:                        if (left == right) {
0224:                            return 0;
0225:                        } else if (left == null) {
0226:                            return -1;
0227:                        } else {
0228:                            return 1;
0229:                        }
0230:                    } else {
0231:                        return left.toString().compareTo(right.toString());
0232:                    }
0233:                }
0234:
0235:            }
0236:
0237:            static class ClassSorterByClassName implements  Comparator {
0238:
0239:                public int compare(Object o1, Object o2) {
0240:                    Class left = (Class) o1;
0241:                    Class right = (Class) o2;
0242:                    int compare = left.getName().compareTo(right.getName());
0243:                    /*if (compare==0)
0244:                    {
0245:                    	if (o1==o2) 
0246:                    	{
0247:                    		return 0;
0248:                    	}
0249:                    	else
0250:                    	{
0251:                    		return 1;
0252:                    	}
0253:                    }
0254:                    else
0255:                    {
0256:                    	return compare;
0257:                    }*/
0258:                    return compare;
0259:                }
0260:            }
0261:
0262:            private String callToString(Object obj, boolean callToString) {
0263:
0264:                try {
0265:                    if (obj == null) {
0266:                        return "null";
0267:                    } else {
0268:                        if (callToString) {
0269:                            return obj.toString();
0270:                        } else {
0271:                            if (obj instanceof  Class) {
0272:                                return obj.toString();
0273:                            } else {
0274:                                return obj.getClass().getName() + "@"
0275:                                        + System.identityHashCode(obj);
0276:                            }
0277:                        }
0278:                    }
0279:
0280:                } catch (Throwable e) {
0281:                    return obj.getClass().getName()
0282:                            + " toString had an Exception ";
0283:                }
0284:            }
0285:
0286:            /** Explore references recursevely */
0287:            private void exploreObject(PrintWriter out, Object source,
0288:                    int currentLevel, final int maxLevel, boolean useToString,
0289:                    boolean weakAndSoft, HashMap mapDataPoints,
0290:                    HashSet alreadyExplored) {
0291:                String level = null;
0292:                {
0293:                    StringBuffer levelStr = new StringBuffer();
0294:                    for (int i = 0; i <= currentLevel; i++) {
0295:                        levelStr.append("!--");
0296:                    }
0297:                    level = levelStr.toString();
0298:                }
0299:
0300:                if (maxLevel >= 0 && currentLevel >= maxLevel) {
0301:                    out.println("<br>" + level + "<b>MaxLevel</b>");
0302:                    return;
0303:                }
0304:                Integer index = new Integer(System.identityHashCode(source));
0305:
0306:                if (alreadyExplored.contains(index)) {
0307:                    if (source instanceof  Class) {
0308:                        out
0309:                                .println("<br>"
0310:                                        + level
0311:                                        + " object instanceOf "
0312:                                        + source
0313:                                        + "@"
0314:                                        + index
0315:                                        + " was already described before on this report");
0316:                    } else {
0317:                        out
0318:                                .println("<br>"
0319:                                        + level
0320:                                        + " object instanceOf "
0321:                                        + source.getClass()
0322:                                        + "@"
0323:                                        + index
0324:                                        + " was already described before on this report");
0325:                    }
0326:                    return;
0327:                }
0328:
0329:                alreadyExplored.add(index);
0330:
0331:                log.info("resolving references of "
0332:                        + callToString(source, useToString) + "...");
0333:                Long sourceTag = new Long(this .getTagOnObject(source));
0334:                ArrayList listPoints = (ArrayList) mapDataPoints.get(sourceTag);
0335:                if (listPoints == null) {
0336:                    log.info("didn't find references");
0337:                    return;
0338:                }
0339:
0340:                log.info("References found");
0341:
0342:                Iterator iter = listPoints.iterator();
0343:
0344:                while (iter.hasNext()) {
0345:                    ReferenceDataPoint point = (ReferenceDataPoint) iter.next();
0346:
0347:                    Object nextReference = treatReference(level, out, point,
0348:                            useToString);
0349:
0350:                    if (nextReference != null && !weakAndSoft) {
0351:                        if (nextReference instanceof  WeakReference
0352:                                || nextReference instanceof  SoftReference) {
0353:                            nextReference = null;
0354:                        }
0355:                    }
0356:
0357:                    if (nextReference != null) {
0358:                        exploreObject(out, nextReference, currentLevel + 1,
0359:                                maxLevel, useToString, weakAndSoft,
0360:                                mapDataPoints, alreadyExplored);
0361:                    }
0362:                }
0363:
0364:            }
0365:
0366:            /** This is used by JSPs to have access to internal features formating results according to the navigations. That's the only reason this method is public. 
0367:             * This is not intended to be used as part of the public API.  
0368:             * @urlBaseToFollow will be concatenated objId=3> obj </a> to the outputStream*/
0369:            public Object treatReference(String level, PrintWriter out,
0370:                    ReferenceDataPoint point, boolean useToString) {
0371:                Object referenceHolder = null;
0372:                if (point.getReferenceHolder() == 0
0373:                        || point.getReferenceHolder() == -1) {
0374:                    referenceHolder = null;
0375:                } else {
0376:                    referenceHolder = this .getObjectOnTag(point
0377:                            .getReferenceHolder());
0378:                }
0379:                Object nextReference = null;
0380:                switch (point.getReferenceType()) {
0381:                case JVMTICallBack.JVMTI_REFERENCE_CLASS:
0382:                    ;// Reference from an object to its class.
0383:                    out.print("<br>" + level + "InstanceOfReference:");
0384:                    out.println("ToString="
0385:                            + callToString(referenceHolder, useToString));
0386:
0387:                    nextReference = referenceHolder;
0388:                    break;
0389:                case JVMTICallBack.JVMTI_REFERENCE_FIELD://Reference from an object to the value of one of its instance fields. For references of this kind the referrer_index parameter to the jvmtiObjectReferenceCallback is the index of the the instance field. The index is based on the order of all the object's fields. This includes all fields of the directly declared static and instance fields in the class, and includes all fields (both public and private) fields declared in superclasses and superinterfaces. The index is thus calculated by summing the index of field in the directly declared class (see GetClassFields), with the total number of fields (both public and private) declared in all superclasses and superinterfaces. The index starts at zero.
0390:                {
0391:
0392:                    String fieldName = null;
0393:
0394:                    if (referenceHolder == null) {
0395:                        fieldName = "Reference GONE";
0396:                    } else {
0397:                        Class clazz = referenceHolder.getClass();
0398:                        Field field = this .getObjectField(clazz, (int) point
0399:                                .getIndex());
0400:                        if (field == null) {
0401:                            fieldName = "UndefinedField@" + referenceHolder;
0402:                        } else {
0403:                            fieldName = field.toString();
0404:                        }
0405:                    }
0406:                    out.print("<br>" + level + " FieldReference " + fieldName
0407:                            + "=" + callToString(referenceHolder, useToString));
0408:                    nextReference = referenceHolder;
0409:                    break;
0410:                }
0411:                case JVMTICallBack.JVMTI_REFERENCE_ARRAY_ELEMENT://Reference from an array to one of its elements. For references of this kind the referrer_index parameter to the jvmtiObjectReferenceCallback is the array index.
0412:                    if (referenceHolder == null) {
0413:                        out.println("<br>" + level + " arrayRef Position "
0414:                                + point.getIndex() + " is gone");
0415:                    } else {
0416:                        out.println("<br>" + level + " arrayRef "
0417:                                + referenceHolder.getClass().getName() + "["
0418:                                + point.getIndex() + "] id=@"
0419:                                + System.identityHashCode(referenceHolder));
0420:                    }
0421:                    nextReference = referenceHolder;
0422:                    break;
0423:                case JVMTICallBack.JVMTI_REFERENCE_CLASS_LOADER://	Reference from a class to its class loader.
0424:                    out.println("<br>" + level + "ClassLoaderReference @ "
0425:                            + callToString(referenceHolder, useToString));
0426:                    nextReference = referenceHolder;
0427:                    break;
0428:                case JVMTICallBack.JVMTI_REFERENCE_SIGNERS://Reference from a class to its signers array.
0429:                    out.println("<br>" + level + "ReferenceSigner@"
0430:                            + callToString(referenceHolder, useToString));
0431:                    nextReference = referenceHolder;
0432:                    break;
0433:                case JVMTICallBack.JVMTI_REFERENCE_PROTECTION_DOMAIN://Reference from a class to its protection domain.
0434:                    out.println("<br>" + level + "ProtectionDomain@"
0435:                            + callToString(referenceHolder, useToString));
0436:                    nextReference = referenceHolder;
0437:                    break;
0438:                case JVMTICallBack.JVMTI_REFERENCE_INTERFACE://Reference from a class to one of its interfaces.
0439:                    out.println("<br>" + level + "ReferenceInterface@"
0440:                            + callToString(referenceHolder, useToString));
0441:                    nextReference = referenceHolder;
0442:                    break;
0443:                case JVMTICallBack.JVMTI_REFERENCE_STATIC_FIELD://Reference from a class to the value of one of its static fields. For references of this kind the referrer_index parameter to the jvmtiObjectReferenceCallback is the index of the static field. The index is based on the order of the directly declared static and instance fields in the class (not inherited fields), starting at zero. See GetClassFields.
0444:                {
0445:                    Class clazz = (Class) referenceHolder;
0446:                    Field field = this .getObjectField(clazz, (int) point
0447:                            .getIndex());
0448:                    String fieldName = null;
0449:                    if (field == null) {
0450:                        fieldName = "UndefinedField@" + referenceHolder;
0451:                    } else {
0452:                        fieldName = field.toString();
0453:                    }
0454:                    out.println("<br>" + level + " StaticFieldReference "
0455:                            + fieldName);
0456:                    nextReference = null;
0457:                    break;
0458:                }
0459:                case JVMTICallBack.JVMTI_REFERENCE_CONSTANT_POOL://Reference from a class to a resolved entry in the constant pool. For references of this kind the referrer_index parameter to the jvmtiObjectReferenceCallback is the index into constant pool table of the class, starting at 1. See The Constant Pool in the Java Virtual Machine Specification.
0460:                    out.println("<br>" + level + "ReferenceInterface@"
0461:                            + callToString(referenceHolder, useToString));
0462:                    nextReference = referenceHolder;
0463:                    break;
0464:                case JVMTICallBack.ROOT_REFERENCE:
0465:                    out.println("<br>" + level + "Root");
0466:                    nextReference = null;
0467:                    break;
0468:                case JVMTICallBack.THREAD_REFERENCE:
0469:                    ;
0470:
0471:                    Class methodClass = this .getMethodClass(point.getMethod());
0472:                    if (methodClass != null) {
0473:                        String className = null;
0474:                        if (methodClass != null) {
0475:                            className = methodClass.getName();
0476:                        }
0477:
0478:                        Thread.yield();
0479:
0480:                        // this is weird but without this sleep here, the JVM crashes. 
0481:                        /*try
0482:                        {
0483:                        	Thread.sleep(10);
0484:                        } catch (InterruptedException e)
0485:                        {
0486:                        	e.printStackTrace();
0487:                        }*/
0488:
0489:                        String methodName = this .getMethodName(point
0490:                                .getMethod());
0491:                        out.println("<br>" + level
0492:                                + " Reference inside a method - " + className
0493:                                + "::" + methodName);
0494:                    }
0495:                    nextReference = null;
0496:                    break;
0497:                default:
0498:                    log.warn("unexpected reference " + point);
0499:                }
0500:                return nextReference;
0501:            }
0502:
0503:            /** This method tags the JVM and return an index. You can navigate through references using this returned HashMap. 
0504:             * This method can't be exposed through JMX as it would serialize a huge amount of data.
0505:             * @return HashMap<Long objectId,ArrayList<ReferenceDataPoint> referencees>
0506:             *  */
0507:            public HashMap createIndexMatrix() throws IOException {
0508:                final HashMap referencesMap = new HashMap();
0509:                File tmpFile = File.createTempFile("tmpRefs", ".tmp");
0510:                this .notifyOnReferences(tmpFile.getAbsolutePath(),
0511:                        new JVMTICallBack() {
0512:                            int count = 0;
0513:
0514:                            public void notifyReference(long referenceHolder,
0515:                                    long referencedObject, long classTag,
0516:                                    long index, long method, byte referenceType) {
0517:                                if (count == 0) {
0518:                                    log.info("started receiving references");
0519:                                }
0520:                                count++;
0521:                                if (count % 1000 == 0) {
0522:                                    log.info(count + " references received");
0523:                                }
0524:                                ReferenceDataPoint dataPoint = new ReferenceDataPoint(
0525:                                        referenceHolder, referencedObject,
0526:                                        classTag, index, method, referenceType);
0527:                                Long indexLong = new Long(referencedObject);
0528:                                ArrayList arrayList = (ArrayList) referencesMap
0529:                                        .get(indexLong);
0530:                                if (arrayList == null) {
0531:                                    arrayList = new ArrayList();
0532:                                    referencesMap.put(indexLong, arrayList);
0533:                                }
0534:                                arrayList.add(dataPoint);
0535:                            }
0536:
0537:                            public void notifyClass(long classTag, Class clazz) {
0538:                            }
0539:
0540:                            public void notifyObject(long classTag,
0541:                                    long objectId, long bytes) {
0542:                            }
0543:                        });
0544:
0545:                tmpFile.delete();
0546:
0547:                return referencesMap;
0548:            }
0549:
0550:            /**
0551:             * Show the reference holders tree of an object
0552:             * @param className The name of the class to explore
0553:             * @param  maxLevel The number of levels to explode. Be careful as if you put this number too high, you migh endup in a forever loop, specially if your object is referencing something too generic
0554:             * @param solveReferencesOnClass Will expose the tree on the class
0555:             * @param solveReferencesOnClassLoader Will expode the tree on the classLoader (I mostly recommend to only look for classLoader's references)
0556:             * @param useToString If true, will use toString when an object is printed. If False will use className@<System.identityHashCode(object)>
0557:             * @param weakAndSoft If false, won't detail references on Weak and Soft References
0558:             * @param printObject If true, Will print (with toString) every single instance of the object passed as parameter 
0559:             */
0560:            public String exploreClassReferences(String className,
0561:                    int maxLevel, boolean solveReferencesOnClasses,
0562:                    boolean solveReferencesOnClassLoaders, boolean useToString,
0563:                    boolean weakAndSoft, boolean printObjects) {
0564:                this .forceGC();
0565:                if (!solveReferencesOnClasses && !solveReferencesOnClassLoaders
0566:                        && !printObjects) {
0567:                    return "<b> you have to select at least solveReferences || solveClassLoaders || printObjects </b>";
0568:                }
0569:
0570:                HashMap referencesMap = null;
0571:                try {
0572:                    referencesMap = createIndexMatrix();
0573:                } catch (Exception e) {
0574:                    CharArrayWriter charArray = new CharArrayWriter();
0575:                    PrintWriter out = new PrintWriter(charArray);
0576:                    e.printStackTrace(out);
0577:                    return charArray.toString();
0578:                }
0579:
0580:                try {
0581:                    return exploreClassReferences(className, maxLevel,
0582:                            solveReferencesOnClasses,
0583:                            solveReferencesOnClassLoaders, useToString,
0584:                            weakAndSoft, printObjects, referencesMap);
0585:                } finally {
0586:                    referencesMap.clear();
0587:                    this .releaseTags();
0588:                }
0589:            }
0590:
0591:            /** This is an overload to reuse the matrix index in case you already have indexed the JVM  */
0592:            public String exploreClassReferences(String className,
0593:                    int maxLevel, boolean solveReferencesOnClasses,
0594:                    boolean solveReferencesOnClassLoaders, boolean useToString,
0595:                    boolean weakAndSoft, boolean printObjects,
0596:                    HashMap referencesMap) {
0597:                CharArrayWriter charArray = new CharArrayWriter();
0598:                PrintWriter out = new PrintWriter(charArray);
0599:
0600:                try {
0601:
0602:                    Class[] loadClasses = this .getLoadedClasses();
0603:
0604:                    for (int i = 0; i < loadClasses.length; i++) {
0605:                        if (loadClasses[i].getName().equals(className)) {
0606:                            out.println("<br><br><br><b>References to "
0607:                                    + loadClasses[i] + "</b>");
0608:                            if (solveReferencesOnClasses)
0609:                                exploreObject(out, loadClasses[i], 0, maxLevel,
0610:                                        useToString, weakAndSoft,
0611:                                        referencesMap, new HashSet());
0612:                            if (solveReferencesOnClassLoaders) {
0613:                                if (loadClasses[i].getClassLoader() != null) {
0614:                                    out
0615:                                            .println("<br><b><i>references to its classloader "
0616:                                                    + loadClasses[i]
0617:                                                            .getClassLoader()
0618:                                                    + "</i></b>");
0619:                                    exploreObject(out, loadClasses[i]
0620:                                            .getClassLoader(), 0, maxLevel,
0621:                                            useToString, weakAndSoft,
0622:                                            referencesMap, new HashSet());
0623:                                }
0624:                            }
0625:                            out.println("<br>");
0626:
0627:                            if (printObjects) {
0628:
0629:                                Object objects[] = this 
0630:                                        .getAllObjects(loadClasses[i]);
0631:                                for (int j = 0; j < objects.length; j++) {
0632:                                    out.println("obj[" + j + "]=" + objects[j]);
0633:                                }
0634:                            }
0635:                        }
0636:                    }
0637:
0638:                    loadClasses = null;
0639:
0640:                    return charArray.toString();
0641:                } catch (Exception e) {
0642:                    charArray = new CharArrayWriter();
0643:                    out = new PrintWriter(charArray);
0644:                    e.printStackTrace(out);
0645:                    return charArray.toString();
0646:                }
0647:            }
0648:
0649:            /**
0650:             * Show the reference holders tree of an object. This method is also exposed through MBean.
0651:             */
0652:            public String exploreObjectReferences(String className,
0653:                    int maxLevel, boolean useToString) {
0654:                this .forceGC();
0655:
0656:                Object obj[] = this .getAllObjects(className);
0657:
0658:                HashMap referencesMap = null;
0659:                try {
0660:                    referencesMap = createIndexMatrix();
0661:                } catch (Exception e) {
0662:                    CharArrayWriter charArray = new CharArrayWriter();
0663:                    PrintWriter out = new PrintWriter(charArray);
0664:                    e.printStackTrace(out);
0665:                    return charArray.toString();
0666:                }
0667:
0668:                CharArrayWriter charArray = new CharArrayWriter();
0669:                PrintWriter out = new PrintWriter(charArray);
0670:
0671:                try {
0672:                    if (obj.length > 100) {
0673:                        out.println("obj List too big (>100)=" + obj.length);
0674:                        return charArray.toString();
0675:                    }
0676:                    for (int i = 0; i < obj.length; i++) {
0677:                        out.println("<br><b>References to obj["
0678:                                + i
0679:                                + "]="
0680:                                + (useToString ? obj[i].toString() : obj[i]
0681:                                        .getClass().getName()));
0682:                        out.println(exploreObjectReferences(referencesMap,
0683:                                obj[i], maxLevel, useToString));
0684:                    }
0685:                    return charArray.toString();
0686:                } finally {
0687:                    referencesMap.clear();
0688:                    this .releaseTags();
0689:                }
0690:            }
0691:
0692:            /**
0693:             * Show the reference holders tree of an object. This returns a report you can visualize through MBean.
0694:             */
0695:            public String exploreObjectReferences(HashMap referencesMap,
0696:                    Object thatObject, int maxLevel, boolean useToString) {
0697:                CharArrayWriter charArray = new CharArrayWriter();
0698:                PrintWriter out = new PrintWriter(charArray);
0699:
0700:                try {
0701:                    exploreObject(out, thatObject, 0, maxLevel, useToString,
0702:                            false, referencesMap, new HashSet());
0703:                    out.println("<br>");
0704:                    return charArray.toString();
0705:                } catch (Exception e) {
0706:                    charArray = new CharArrayWriter();
0707:                    out = new PrintWriter(charArray);
0708:                    e.printStackTrace(out);
0709:                    return charArray.toString();
0710:                }
0711:            }
0712:
0713:            /** Forces an OutOfMemoryError and releases the memory immediatly. This will force SoftReferences to go away. */
0714:            public void forceReleaseOnSoftReferences() {
0715:                SoftReference reference = new SoftReference(new Object());
0716:
0717:                ArrayList list = new ArrayList();
0718:                int i = 0;
0719:                try {
0720:                    while (true) {
0721:                        list
0722:                                .add("A Big String A Big String A Big String A Big String A Big String A Big String A Big String A Big String A Big String A Big String A Big String "
0723:                                        + (i++));
0724:                        if (i % 1000 == 0) // doing the check on each 100 elements
0725:                        {
0726:                            if (reference.get() == null) {
0727:                                System.out
0728:                                        .println("Break as the soft reference was gone");
0729:                                break;
0730:                            }
0731:                        }
0732:                    }
0733:                } catch (Throwable e) {
0734:                }
0735:
0736:                list.clear();
0737:                try {
0738:                    ByteArrayOutputStream byteout = new ByteArrayOutputStream();
0739:                    ObjectOutputStream out = new ObjectOutputStream(byteout);
0740:
0741:                    out.writeObject(new Dummy());
0742:
0743:                    ByteArrayInputStream byteInput = new ByteArrayInputStream(
0744:                            byteout.toByteArray());
0745:                    ObjectInputStream input = new ObjectInputStream(byteInput);
0746:                    input.readObject();
0747:
0748:                } catch (Exception e) {
0749:                    e.printStackTrace();
0750:                }
0751:
0752:                this .forceGC();
0753:            }
0754:
0755:            /** Used just to serialize anything and release SoftCache on java Serialization */
0756:            static class Dummy implements  Serializable {
0757:                private static final long serialVersionUID = 1L;
0758:            }
0759:
0760:            /** 
0761:             * Will show a report of every class loaded on this JVM. At the beggining of the report you will see duplicated classes (classes loaded in more than one classLoader)
0762:             */
0763:            public String listClassesHTMLReport() throws Exception {
0764:                try {
0765:                    forceGC();
0766:                    CharArrayWriter charArray = new CharArrayWriter();
0767:                    PrintWriter out = new PrintWriter(charArray);
0768:
0769:                    Collection classSet = createTreeSet(new ClassSorterByClassName());
0770:
0771:                    boolean printedHeader = false;
0772:
0773:                    ClassLoader systemClassLoaderDummy = new ClassLoader() {
0774:                        public String toString() {
0775:                            return "SystemClassLoader";
0776:                        }
0777:                    };
0778:                    ArrayList classLoaderDuplicates = new ArrayList();
0779:                    Iterator iter = classSet.iterator();
0780:                    String currentName = null;
0781:                    Class currentClass = null;
0782:                    while (iter.hasNext()) {
0783:                        currentClass = (Class) iter.next();
0784:                        if (currentName != currentClass.getName()) {
0785:                            if (classLoaderDuplicates.size() > 1) {
0786:                                if (!printedHeader) {
0787:                                    out
0788:                                            .println("<br><b>List of duplicated classes</b>");
0789:                                    printedHeader = true;
0790:                                }
0791:
0792:                                out
0793:                                        .println("<br>"
0794:                                                + "<b> Class "
0795:                                                + currentName
0796:                                                + " was loaded on these classLoaders:</b>");
0797:                                Iterator iterClassLoader = classLoaderDuplicates
0798:                                        .iterator();
0799:                                while (iterClassLoader.hasNext()) {
0800:                                    ClassLoader loader = (ClassLoader) iterClassLoader
0801:                                            .next();
0802:                                    out.println("<br>" + loader.toString());
0803:                                }
0804:
0805:                            }
0806:                            currentName = currentClass.getName();
0807:                            classLoaderDuplicates.clear();
0808:                        }
0809:
0810:                        ClassLoader loader = currentClass.getClassLoader();
0811:                        if (loader == null) {
0812:                            loader = systemClassLoaderDummy;
0813:                        }
0814:                        classLoaderDuplicates.add(loader);
0815:
0816:                        currentName = currentClass.getName();
0817:                    }
0818:
0819:                    if (classLoaderDuplicates.size() > 1) {
0820:                        out.println("<br>" + "<b> Class " + currentName
0821:                                + " was loaded on these classLoaders:</b>");
0822:                        Iterator iterClassLoader = classLoaderDuplicates
0823:                                .iterator();
0824:                        while (iterClassLoader.hasNext()) {
0825:                            ClassLoader loader = (ClassLoader) iterClassLoader
0826:                                    .next();
0827:                            out.println("<br>" + loader.toString());
0828:                        }
0829:
0830:                    }
0831:
0832:                    out.println("<br><b>List of classes by ClassLoader</b>");
0833:                    classSet = retrieveLoadedClassesByClassLoader();
0834:
0835:                    // I will need a dummy reference, as the first classLoader on the iterator will be null
0836:                    ClassLoader currentClassLoader = new ClassLoader() {
0837:                    };
0838:                    out.println("<br>");
0839:
0840:                    iter = classSet.iterator();
0841:                    while (iter.hasNext()) {
0842:                        Class clazz = (Class) iter.next();
0843:                        if (currentClassLoader != clazz.getClassLoader()) {
0844:                            currentClassLoader = clazz.getClassLoader();
0845:                            out
0846:                                    .println("<br><b>ClassLoader = "
0847:                                            + (currentClassLoader == null ? "System Class Loader"
0848:                                                    : (currentClassLoader
0849:                                                            .toString()))
0850:                                            + "</b>");
0851:                        }
0852:                        out.println("Class = " + clazz.getName());
0853:                    }
0854:
0855:                    return new String(charArray.toCharArray());
0856:                } catch (Exception e) {
0857:                    e.printStackTrace();
0858:                    throw e;
0859:                }
0860:            }
0861:
0862:            /** Used by JSPs and JMX to report */
0863:            public Collection retrieveLoadedClassesByClassName() {
0864:                Collection classSet;
0865:                classSet = createTreeSet(new ClassSorterByClassName());
0866:                return classSet;
0867:            }
0868:
0869:            /** Used by JSPs and JMX to report */
0870:            public Collection retrieveLoadedClassesByClassLoader() {
0871:                Collection classSet;
0872:                classSet = createTreeSet(new ClassSorterByClassLoader());
0873:                return classSet;
0874:            }
0875:
0876:            private Collection createTreeSet(Comparator comparator) {
0877:                Class[] classes = this .getLoadedClasses();
0878:
0879:                ArrayList classSet = new ArrayList();
0880:
0881:                for (int i = 0; i < classes.length; i++) {
0882:                    classSet.add(classes[i]);
0883:                }
0884:
0885:                Collections.sort(classSet, comparator);
0886:                return classSet;
0887:            }
0888:
0889:            static class InnerCallBack implements  JVMTICallBack {
0890:
0891:                TLongObjectHashMap classesMap = new TLongObjectHashMap();
0892:                WeakHashMap maps = new WeakHashMap();
0893:
0894:                public void notifyClass(long classTag, Class clazz) {
0895:                    classesMap.put(classTag, clazz);
0896:                }
0897:
0898:                public void notifyObject(long classTag, long objectId,
0899:                        long bytes) {
0900:                    Class clazz = (Class) classesMap.get(classTag);
0901:
0902:                    if (clazz != null) // this is not supposed to happen, but just in case I keep this if here
0903:                    {
0904:                        InventoryDataPoint point = (InventoryDataPoint) maps
0905:                                .get(clazz);
0906:                        if (point == null) {
0907:                            point = new InventoryDataPoint(clazz);
0908:                            maps.put(clazz, point);
0909:                        }
0910:
0911:                        point.bytes += bytes;
0912:                        point.instances++;
0913:                    }
0914:
0915:                }
0916:
0917:                public void notifyReference(long referenceHolder,
0918:                        long referencedObject, long classTag, long index,
0919:                        long method, byte referenceType) {
0920:                }
0921:
0922:            }
0923:
0924:            /**
0925:             * It will return true if the comparisson didn't represent any changes.
0926:             * This can be used by JUnitTests to validate the consumption of the memory is on the expected results.
0927:             * @param reportOutput You could set System.out here. The location where logging information is going to be sent.
0928:             * @param map1 The first snapshot.
0929:             * @param map2 The second snapshot.
0930:             * @param ignoredClasses Classes you want to ignore on the comparisson. Used to ignore things you know are going to be produced and you don't have control over the testcase.
0931:             * @param prefixesToIgnore Same thing as classes, but every classes starting with these prefixes are going to be ignored.
0932:             * @param expectedIncreases An array of InventoryDataPoint with the maximum number of instances each class could be generating.
0933:             * @return true if the assertion is okay
0934:             */
0935:            public boolean compareInventories(PrintStream reportOutput,
0936:                    Map map1, Map map2, Class[] ignoredClasses,
0937:                    String[] prefixesToIgnore,
0938:                    InventoryDataPoint[] expectedIncreases) {
0939:                HashSet ignoredItems = new HashSet();
0940:                if (ignoredClasses != null) {
0941:                    for (int i = 0; i < ignoredClasses.length; i++) {
0942:                        ignoredItems.add(ignoredClasses[i]);
0943:                    }
0944:                }
0945:
0946:                HashMap expectedIncreasesHash = new HashMap();
0947:                if (expectedIncreases != null) {
0948:                    for (int i = 0; i < expectedIncreases.length; i++) {
0949:                        Class clazz = expectedIncreases[i].getClazz();
0950:                        expectedIncreasesHash.put(clazz, expectedIncreases[i]);
0951:                    }
0952:                }
0953:
0954:                // expected increase based on map1's size
0955:                addExpectedIncrease(expectedIncreasesHash,
0956:                        "java.lang.ref.ReferenceQueue$Lock", 1);
0957:                addExpectedIncrease(expectedIncreasesHash,
0958:                        "java.util.WeakHashMap", 1);
0959:                addExpectedIncrease(expectedIncreasesHash,
0960:                        "java.lang.ref.ReferenceQueue", 1);
0961:                addExpectedIncrease(expectedIncreasesHash,
0962:                        "[Ljava.util.WeakHashMap$Entry;", 1);
0963:                addExpectedIncrease(expectedIncreasesHash,
0964:                        "java.lang.ref.WeakReference", map1.size());
0965:                addExpectedIncrease(expectedIncreasesHash,
0966:                        "java.util.WeakHashMap$Entry", map1.size());
0967:
0968:                boolean reportOK = true;
0969:
0970:                Iterator iterMap1 = map1.entrySet().iterator();
0971:                while (iterMap1.hasNext()) {
0972:                    Map.Entry entry = (Map.Entry) iterMap1.next();
0973:                    Class clazz = (Class) entry.getKey();
0974:
0975:                    boolean isIgnoredPrefix = false;
0976:                    if (prefixesToIgnore != null) {
0977:                        for (int i = 0; i < prefixesToIgnore.length; i++) {
0978:                            if (clazz.getName().startsWith(prefixesToIgnore[i])) {
0979:                                isIgnoredPrefix = true;
0980:                                break;
0981:                            }
0982:                        }
0983:                    }
0984:                    if (!isIgnoredPrefix
0985:                            && !ignoredItems.contains(entry.getKey())) {
0986:                        InventoryDataPoint point1 = (InventoryDataPoint) entry
0987:                                .getValue();
0988:                        InventoryDataPoint point2 = (InventoryDataPoint) map2
0989:                                .get(clazz);
0990:                        if (point2 != null) {
0991:                            if (point2.getInstances() > point1.getInstances()) {
0992:                                InventoryDataPoint expectedIncrease = (InventoryDataPoint) expectedIncreasesHash
0993:                                        .get(clazz);
0994:                                boolean failed = true;
0995:                                if (expectedIncrease != null) {
0996:                                    if ((point2.getInstances() - point1
0997:                                            .getInstances()) <= expectedIncrease
0998:                                            .getInstances()) {
0999:                                        failed = false;
1000:                                    }
1001:                                }
1002:                                if (failed) {
1003:                                    int expected = 0;
1004:                                    if (expectedIncrease != null) {
1005:                                        expected = expectedIncrease
1006:                                                .getInstances();
1007:                                    }
1008:                                    reportOK = false;
1009:                                    reportOutput
1010:                                            .println("<br> Class "
1011:                                                    + clazz.getName()
1012:                                                    + " had an increase of "
1013:                                                    + ((point2.getInstances() - point1
1014:                                                            .getInstances()) - expected)
1015:                                                    + " instances represented by "
1016:                                                    + (point2.getBytes() - point1
1017:                                                            .getBytes())
1018:                                                    + " bytes");
1019:                                    if (expectedIncrease != null) {
1020:                                        reportOutput
1021:                                                .print("<br> "
1022:                                                        + ((point2
1023:                                                                .getInstances() - point1
1024:                                                                .getInstances()) - expectedIncrease
1025:                                                                .getInstances())
1026:                                                        + " higher than expected");
1027:                                    }
1028:
1029:                                }
1030:                            }
1031:                        }
1032:                    }
1033:                }
1034:
1035:                return reportOK;
1036:            }
1037:
1038:            private void addExpectedIncrease(HashMap expectedIncreasesHash,
1039:                    String name, int numberOfInstances) {
1040:                Class tmpClass = getClassByName(name);
1041:                if (tmpClass != null) {
1042:                    expectedIncreasesHash.put(tmpClass, new InventoryDataPoint(
1043:                            tmpClass, numberOfInstances));
1044:                }
1045:            }
1046:
1047:            /** Returns a WeakHashMap<Class,InventoryDataPoint> summarizing the current JVM's inventory.
1048:             *  */
1049:            public Map produceInventory() throws IOException {
1050:                this .forceGC();
1051:                InnerCallBack callBack = new InnerCallBack();
1052:                File tmpFileObjects = File.createTempFile("delete-me",
1053:                        ".objects");
1054:                try {
1055:                    notifyInventory(true, null, tmpFileObjects
1056:                            .getAbsolutePath(), callBack);
1057:                } finally {
1058:                    if (tmpFileObjects.exists()) {
1059:                        try {
1060:                            tmpFileObjects.delete();
1061:                        } catch (Exception ignored) {
1062:                        }
1063:                    }
1064:                }
1065:
1066:                return callBack.maps;
1067:            }
1068:
1069:            /** Will list the current memory inventory. Exposed through JMX.  */
1070:            public String inventoryReport() throws Exception {
1071:                Map map = produceInventory();
1072:
1073:                TreeSet valuesSet = new TreeSet(map.values());
1074:                Iterator iterDataPoints = valuesSet.iterator();
1075:                CharArrayWriter charArray = new CharArrayWriter();
1076:                PrintWriter out = new PrintWriter(charArray);
1077:
1078:                out
1079:                        .println("<table><tr><td>Class</td><td>#Instances</td><td>#Bytes</td></tr>");
1080:
1081:                while (iterDataPoints.hasNext()) {
1082:                    InventoryDataPoint point = (InventoryDataPoint) iterDataPoints
1083:                            .next();
1084:                    out.println("<tr><td>" + point.getClazz().getName()
1085:                            + "</td><td>" + point.getInstances() + "</td><td>"
1086:                            + point.getBytes() + "</td></tr>");
1087:                }
1088:                out.println("</table>");
1089:
1090:                return charArray.toString();
1091:            }
1092:
1093:            /** Will print a report of every instance of the class passed by parameter. Exposed through JMX .  */
1094:            public String printObjects(String className) throws Exception {
1095:                CharArrayWriter charArray = new CharArrayWriter();
1096:                PrintWriter out = new PrintWriter(charArray);
1097:
1098:                Object objects[] = this .getAllObjects(className);
1099:
1100:                out.println("<table>");
1101:                for (int i = 0; i < objects.length; i++) {
1102:                    out.println("<tr><td>");
1103:                    out.println(objects[i]);
1104:                    if (objects[i] instanceof  Object[]) {
1105:                        out.println("</td><td>");
1106:                        out.println("array of "
1107:                                + ((Object[]) objects[i]).length);
1108:                        out.println("</td></tr>");
1109:                    }
1110:                }
1111:
1112:                out.println("</table>");
1113:
1114:                return charArray.toString();
1115:            }
1116:
1117:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.