Source Code Cross Referenced for ClassRepository.java in  » IDE-Netbeans » cvsclient » org » netbeans » lib » profiler » classfile » 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 » IDE Netbeans » cvsclient » org.netbeans.lib.profiler.classfile 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003:         *
004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005:         *
006:         * The contents of this file are subject to the terms of either the GNU
007:         * General Public License Version 2 only ("GPL") or the Common
008:         * Development and Distribution License("CDDL") (collectively, the
009:         * "License"). You may not use this file except in compliance with the
010:         * License. You can obtain a copy of the License at
011:         * http://www.netbeans.org/cddl-gplv2.html
012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013:         * specific language governing permissions and limitations under the
014:         * License.  When distributing the software, include this License Header
015:         * Notice in each file and include the License file at
016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
017:         * particular file as subject to the "Classpath" exception as provided
018:         * by Sun in the GPL Version 2 section of the License file that
019:         * accompanied this code. If applicable, add the following below the
020:         * License Header, with the fields enclosed by brackets [] replaced by
021:         * your own identifying information:
022:         * "Portions Copyrighted [year] [name of copyright owner]"
023:         *
024:         * Contributor(s):
025:         * The Original Software is NetBeans. The Initial Developer of the Original
026:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027:         * Microsystems, Inc. All Rights Reserved.
028:         *
029:         * If you wish your version of this file to be governed by only the CDDL
030:         * or only the GPL Version 2, indicate your decision by adding
031:         * "[Contributor] elects to include this software in this distribution
032:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
033:         * single choice of license, a recipient has the option to distribute
034:         * your version of this file under either the CDDL, the GPL Version 2 or
035:         * to extend the choice of license to its licensees as provided above.
036:         * However, if you add GPL Version 2 code and therefore, elected the GPL
037:         * Version 2 license, then the option applies only if the new code is
038:         * made subject to such option by the copyright holder.
039:         */
040:
041:        package org.netbeans.lib.profiler.classfile;
042:
043:        import org.netbeans.lib.profiler.TargetAppRunner;
044:        import org.netbeans.lib.profiler.global.CommonConstants;
045:        import org.netbeans.lib.profiler.instrumentation.BadLocationException;
046:        import org.netbeans.lib.profiler.utils.FileOrZipEntry;
047:        import org.netbeans.lib.profiler.utils.MiscUtils;
048:        import java.io.File;
049:        import java.io.FilenameFilter;
050:        import java.io.IOException;
051:        import java.util.*;
052:
053:        /**
054:         * A collection of several static methods for general class file reading functionality. Allows to set
055:         * a class path, read a class from class path, generate a class that does not have a .class file (such
056:         * as an array class), etc. It also keeps track of classes ever loaded by it, and allows one to iterate
057:         * over these classes.
058:         *
059:         * @author Tomas Hurka
060:         * @author Misha Dmitirev
061:         */
062:        public abstract class ClassRepository implements  CommonConstants {
063:            //~ Inner Classes ------------------------------------------------------------------------------------------------------------
064:
065:            // ------------------------ Method-class-source related stuff --------------------------------
066:            public static class CodeRegionBCI {
067:                //~ Instance fields ------------------------------------------------------------------------------------------------------
068:
069:                public String className;
070:                public String methodName;
071:                public String methodSignature;
072:                public int bci0;
073:                public int bci1;
074:
075:                //~ Constructors ---------------------------------------------------------------------------------------------------------
076:
077:                public CodeRegionBCI(String className, String methodName,
078:                        String methodSignature, int bci0, int bci1) {
079:                    this .className = className;
080:                    this .methodName = methodName;
081:                    this .methodSignature = methodSignature;
082:                    this .bci0 = bci0;
083:                    this .bci1 = bci1;
084:                }
085:
086:                //~ Methods --------------------------------------------------------------------------------------------------------------
087:
088:                public String toString() {
089:                    return "CodeRegionBCI [" // NOI18N
090:                            + "className: " + className // NOI18N
091:                            + ", methodName: " + methodName // NOI18N
092:                            + ", methodSignature: " + methodSignature // NOI18N
093:                            + ", bci0: " + bci0 // NOI18N
094:                            + ", bci1: " + bci1 // NOI18N
095:                            + "]"; // NOI18N
096:                }
097:            }
098:
099:            //~ Static fields/initializers -----------------------------------------------------------------------------------------------
100:
101:            // The below class file location signals to ClassFileCache that the class file should have been already supplied by the VM.
102:            static final String LOCATION_VMSUPPLIED = "<VM_SUPPLIED>"; // NOI18N
103:            private static ClassPath classPath;
104:            private static Hashtable classes;
105:            private static HashSet notFoundClasses;
106:            private static Map definingClassLoaderMap;
107:
108:            static {
109:                clearCache();
110:            }
111:
112:            //~ Methods ------------------------------------------------------------------------------------------------------------------
113:
114:            public static ArrayList getAllClassVersions(String className) {
115:                className = className.replace('.', '/').intern(); // NOI18N
116:
117:                Object entry = classes.get(className);
118:
119:                if (entry != null) { // A single class or placeholder, or a group of them for this name, exists
120:
121:                    ArrayList ret = new ArrayList();
122:
123:                    if (entry instanceof  BaseClassInfo) {
124:                        ret.add(entry);
125:                    } else {
126:                        ret = ((SameNameClassGroup) entry).getAll();
127:                    }
128:
129:                    return ret;
130:                } else {
131:                    return null;
132:                }
133:            }
134:
135:            public static Enumeration getClassEnumerationWithAllVersions() {
136:                class ClassesEnumeration implements  Enumeration {
137:                    private Enumeration baseEnum;
138:                    private Object nextElement;
139:                    private ArrayList classes;
140:                    private int idx;
141:
142:                    ClassesEnumeration(Enumeration baseEnum) {
143:                        this .baseEnum = baseEnum;
144:                    }
145:
146:                    public boolean hasMoreElements() {
147:                        if (nextElement == null) {
148:                            return baseEnum.hasMoreElements();
149:                        } else {
150:                            return true;
151:                        }
152:                    }
153:
154:                    public Object nextElement() {
155:                        if (nextElement != null) {
156:                            Object ret = nextElement;
157:                            idx++;
158:
159:                            if (idx == classes.size()) {
160:                                nextElement = null;
161:                            } else {
162:                                nextElement = classes.get(idx);
163:                            }
164:
165:                            return ret;
166:                        } else {
167:                            Object next = baseEnum.nextElement();
168:
169:                            if (next instanceof  SameNameClassGroup) {
170:                                SameNameClassGroup g = (SameNameClassGroup) next;
171:                                classes = g.getAll();
172:                                next = classes.get(0);
173:
174:                                if (classes.size() > 1) {
175:                                    idx = 1;
176:                                    nextElement = classes.get(1);
177:                                } else {
178:                                    classes = null;
179:                                }
180:                            }
181:
182:                            return next;
183:                        }
184:                    }
185:                }
186:
187:                return new ClassesEnumeration(classes.elements());
188:            }
189:
190:            public static ClassPath getClassPath() {
191:                return classPath;
192:            }
193:
194:            /**
195:             * Returns names of all classes that can be located on the given classpath.
196:             * Since this method performs directory scanning, it is recommended to call it once and cache the results.
197:             */
198:            public static ArrayList getClassesOnClasspath(
199:                    ArrayList classPathElementList) { // TODO CHECK: unused method
200:
201:                ArrayList list = new ArrayList();
202:                list.addAll(classPathElementList);
203:
204:                ArrayList res = new ArrayList();
205:
206:                for (Iterator e = list.iterator(); e.hasNext();) {
207:                    String dirOrJar = (String) e.next();
208:
209:                    if (!(dirOrJar.endsWith(".jar") || dirOrJar
210:                            .endsWith(".zip"))) // NOI18N
211:                    {
212:                        MiscUtils.getAllClassesInDir(dirOrJar, "", true, res); // NOI18N
213:                    } else {
214:                        MiscUtils.getAllClassesInJar(dirOrJar, true, res);
215:                    }
216:                }
217:
218:                return res;
219:            }
220:
221:            public static CodeRegionBCI getMethodForSourceRegion(
222:                    ClassInfo clazz, int startLine, int endLine)
223:                    throws ClassNotFoundException, IOException,
224:                    BadLocationException {
225:                if (startLine > endLine) {
226:                    return null; // Just in case...
227:                }
228:
229:                int[] idxAndBCI0 = clazz
230:                        .methodIdxAndBestBCIForLineNo(startLine);
231:                int methodIdx = idxAndBCI0[0];
232:
233:                if (methodIdx >= 0) {
234:                    String methodName = clazz.getMethodNames()[methodIdx];
235:
236:                    if ((methodName == "<init>") || (methodName == "<clinit>")) { // NOI18N
237:                        // See the comment in ClassInfo.methodIdxAndBestBCIForLineNo() regarding initializers scattered about the class text.
238:                        // Check if a method in a nested class matches the same spot in the source code.
239:
240:                        CodeRegionBCI res = getMethodForSourceRegionInNestedClasses(
241:                                clazz, startLine, endLine);
242:
243:                        if (res != null) {
244:                            return res;
245:                        }
246:                    }
247:
248:                    int[] minAndMaxLines = clazz
249:                            .getMinAndMaxLinesForMethod(methodIdx);
250:
251:                    if (endLine <= minAndMaxLines[1]) {
252:                        endLine++; // That's because we will need to inject code after the *last bytecode corresponding to endLine*
253:                    }
254:
255:                    int[] idxAndBCI1 = clazz
256:                            .methodIdxAndBestBCIForLineNo(endLine);
257:
258:                    // Now let's check if start and end lines are within the same method.
259:                    // If the end line is definitely within some other method, it's an error and we return.
260:                    // However, it may just cover one or more of '}'s in the end of this method, and these lines
261:                    // are just not within this method's line number table. If so, assume that the end line is
262:                    // the last line of the this method.
263:                    if (methodIdx != idxAndBCI1[0]) {
264:                        if (idxAndBCI1[0] != -1) { // Definitely this line belongs to some other method
265:
266:                            return null;
267:                        } else { // Couldn't find the line - assume it's the last line of the same method
268:                            idxAndBCI1[0] = methodIdx;
269:
270:                            // Need to find the bci of the last instruction in this method. It can only be a "return" or 'goto' ('goto_w').
271:                            // In either case, we should put the call before this instruction, since it would make no sense after it.
272:                            byte[] codeBytes = clazz
273:                                    .getMethodBytecode(methodIdx);
274:                            idxAndBCI1[1] = ClassInfo.findPreviousBCI(
275:                                    codeBytes, codeBytes.length);
276:                        }
277:                    }
278:
279:                    // Now here is another issue. It appears that at least "while() { }" is effectively compiled as "do..while",
280:                    // i.e. the condition check is located after the block, not before. Which leads to the problem: if the
281:                    // user points at the line with "while" as a first region line, the "exact" bytecode offset for this particular
282:                    // line may be greater than the offset for the next line after "while"! This leads to incorrect measurements
283:                    // results at best and to the JVM crash during bytecode oop map generation at worst. To handle this, we
284:                    // currently use heuristics which just looks up the line with the smallest bci in between startLine and endLine.
285:                    int bestBCI0 = idxAndBCI0[1];
286:
287:                    for (int lineNo = startLine + 1; lineNo < (endLine - 1); lineNo++) {
288:                        int otherBestBCI0 = clazz.bciForMethodAndLineNo(
289:                                methodIdx, lineNo);
290:
291:                        if (otherBestBCI0 < bestBCI0) {
292:                            bestBCI0 = otherBestBCI0;
293:                        }
294:                    }
295:
296:                    // Finally, check if the last bci is of the "goto" opcode. If so, we should actually return the bci of the
297:                    // previous opcode, since injecting code probe right after the "goto", as it will be done if no measures are
298:                    // taken, makes no sense. This code will not work as intended, and most likely will be just unreachable.
299:                    // THIS IS INCORRECT. We inject code *before*, not after, the given bytecode. So it can be goto as well.
300:                    //idxAndBCI1[1] = clazz.checkIfAtGoTo(methodIdx, idxAndBCI1[1]);
301:                    return new CodeRegionBCI(clazz.getName(), clazz
302:                            .getMethodNames()[methodIdx], clazz
303:                            .getMethodSignatures()[methodIdx], bestBCI0,
304:                            idxAndBCI1[1]);
305:                } else if (methodIdx == -2) { // No line number tables in this class
306:                    throw new BadLocationException(
307:                            "Class does not have source line number tables.\nRecompile it with appropriate options."); // NOI18N
308:                }
309:
310:                // Suitable method not found. Look at nested classes, if there are any.
311:                return getMethodForSourceRegionInNestedClasses(clazz,
312:                        startLine, endLine);
313:            }
314:
315:            /*  public static int[] getMinAndMaxLinesForMethod(String className, String methodName, String methodSignature)  // TODO CHECK: unused method
316:               throws IOException, ClassFormatError {
317:               ClassInfo clazz = lookupClassOnAllPaths(className);
318:               String methodNames[] = clazz.getMethodNames();
319:               String methodSignatures[] = clazz.getMethodSignatures();
320:               methodName = methodName.intern();
321:               methodSignature = methodSignature.intern();
322:               int idx = clazz.getMethodIndex(methodName, methodSignature);
323:               if (idx != -1)
324:                 return clazz.getMinAndMaxLinesForMethod(idx);
325:               else
326:                 return null;
327:               }
328:             */
329:            public static CodeRegionBCI getMethodMinAndMaxBCI(ClassInfo clazz,
330:                    String methodName, String methodSignature) {
331:                methodName = methodName.intern();
332:                methodSignature = methodSignature.intern();
333:
334:                int idx = clazz.getMethodIndex(methodName, methodSignature);
335:
336:                if (idx == -1) {
337:                    return null;
338:                }
339:
340:                // Note that className and clazz.getName() may be different, e.g. if className is specified as "x.y.Outer.Inner",
341:                // when the correct format understood by the rest of JFluid is "x.y.Outer$Inner".
342:                return new CodeRegionBCI(clazz.getName(), methodName,
343:                        methodSignature, 0,
344:                        clazz.getMethodBytecode(idx).length - 1);
345:            }
346:
347:            public static void addPlaceholder(PlaceholderClassInfo pci) {
348:                BaseClassInfo singleExistingClazzOrPCI = null;
349:                SameNameClassGroup classGroup = null;
350:                String className = pci.getName();
351:
352:                Object entry = classes.get(className);
353:
354:                if (entry != null) { // A single class or placeholder, or a group of them for this name, exists
355:
356:                    if (entry instanceof  BaseClassInfo) {
357:                        singleExistingClazzOrPCI = (BaseClassInfo) entry;
358:                        classGroup = new SameNameClassGroup();
359:                        classGroup.add(singleExistingClazzOrPCI);
360:                        classGroup.add(pci);
361:                        classes.put(className, classGroup);
362:                    } else { // entry is a SameNameClassGroup
363:                        classGroup = (SameNameClassGroup) entry;
364:                        classGroup.add(pci);
365:                    }
366:                } else { // An entry with this name doesn't exist
367:                    classes.put(className, pci);
368:                }
369:            }
370:
371:            /** Adds a VM-supplied class file to the class file cache, but not to this repository's hashtable yet. */
372:            public static void addVMSuppliedClassFile(String className,
373:                    int classLoaderId, byte[] buf) {
374:                className = className.replace('.', '/').intern(); // NOI18N
375:                ClassFileCache.getDefault().addVMSuppliedClassFile(className,
376:                        classLoaderId, buf);
377:            }
378:
379:            /** Utility method - read .class file and return class name stored in it. */
380:            public static ClassInfo classInfoForFile(File f)
381:                    throws ClassNotFoundException, IOException,
382:                    ClassFormatError { // TODO CHECK: unused method
383:
384:                byte[] buf = MiscUtils
385:                        .readFileIntoBuffer(new FileOrZipEntry(f));
386:                ClassInfo clazz = new ClassInfo(buf) {
387:                    protected byte[] getClassFileBytes() {
388:                        return null;
389:                    }
390:                };
391:
392:                String fileName = f.getCanonicalPath();
393:                String className = clazz.getName() + ".class"; // NOI18N
394:                String expectedClassName = fileName.substring(
395:                        fileName.length() - className.length()).replace('\\',
396:                        '/'); // NOI18N
397:
398:                if (!className.equals(expectedClassName)) {
399:                    throw new ClassNotFoundException(
400:                            "Mismatch between name in .class file and location for "
401:                                    + fileName // NOI18N
402:                                    + "\nYour class path setting may be incorrect." // NOI18N
403:                    ); // NOI18N
404:                }
405:
406:                return clazz;
407:            }
408:
409:            /** Should be called after profiling finishes to cleanup any static data, close opened files, etc. */
410:            public static void cleanup() {
411:                clearCache();
412:
413:                if (classPath != null) {
414:                    classPath.close();
415:                    classPath = null;
416:                }
417:            }
418:
419:            /** Will reset any cached data, will not reset data pertinent to session in progress */
420:            public static void clearCache() {
421:                classes = new Hashtable();
422:                ClassFileCache.resetDefaultCache();
423:                notFoundClasses = new HashSet();
424:                definingClassLoaderMap = new HashMap();
425:            }
426:
427:            /**
428:             * This is the ClassRepository internal class path initialization method. The class path is initialized to the
429:             * combination of the running VM's boot, extension and main class paths (if they are available; otherwise only
430:             * the main path is obtained from the tool's settings), plus the secondary class path from the settings.
431:             *
432:             * @param workingDir            working directory, needed in case the given paths are in the local form
433:             * @param classPaths            the 3 elements should be the user, extension, and boot class paths, respectively
434:             */
435:            public static void initClassPaths(String workingDir,
436:                    String[] classPaths) {
437:                ArrayList userClassPathElementList = MiscUtils
438:                        .getPathComponents(classPaths[0], true, workingDir);
439:                ArrayList bootClassPathElementList = MiscUtils
440:                        .getPathComponents(classPaths[2], true, workingDir);
441:
442:                String extPath = classPaths[1];
443:                ArrayList extClassPathElementList = new ArrayList();
444:
445:                // Extension class path needs special handling, since it consists of directories, which contain .jars
446:                // So we need to find all these .jars in all these dirs and add them to extClassPathElementList
447:                ArrayList dirs = MiscUtils.getPathComponents(extPath, true,
448:                        workingDir);
449:
450:                for (Iterator e = dirs.iterator(); e.hasNext();) {
451:                    File extDir = new File((String) e.next());
452:                    String[] extensions = extDir.list(new FilenameFilter() {
453:                        public boolean accept(File dir, String name) {
454:                            name = name.toLowerCase();
455:
456:                            return name.endsWith(".zip")
457:                                    || name.endsWith(".jar"); // NOI18N
458:                        }
459:                    });
460:
461:                    if (extensions == null) {
462:                        continue;
463:                    }
464:
465:                    for (int i = 0; i < extensions.length; i++) {
466:                        extClassPathElementList.add(extPath
467:                                + File.separatorChar + extensions[i]);
468:                    }
469:                }
470:
471:                ArrayList list = new ArrayList();
472:                list.addAll(bootClassPathElementList);
473:                list.addAll(extClassPathElementList);
474:                list.addAll(userClassPathElementList);
475:
476:                StringBuffer buf = new StringBuffer();
477:
478:                for (Iterator e = list.iterator(); e.hasNext();) {
479:                    buf.append((String) e.next());
480:
481:                    if (e.hasNext()) {
482:                        buf.append(File.pathSeparatorChar);
483:                    }
484:                }
485:
486:                classPath = new ClassPath(buf.toString(), true);
487:
488:                notFoundClasses = new HashSet();
489:            }
490:
491:            /**
492:             * Lookup a class in the class repository. If it's not there, look it up on the classpath (for classes with 0 loader)
493:             * or in the cache of VM-supplied classes. If the class is not found anywhere, reports this and returns null.
494:             * Guaranteed to return a real class or null, but not a placeholder. Should not be called for special (array)
495:             * classes - there is lookupSpecialClass() for that.
496:             */
497:            public static DynamicClassInfo lookupClass(String className,
498:                    int classLoaderId) throws IOException, ClassFormatError {
499:                return lookupClass(className, classLoaderId, true);
500:            }
501:
502:            /**
503:             * Lookup a class in the class repository. If it's not there, don't bother checking the classpath etc. - just
504:             * return an instance of PlaceholderClassInfo. The rationale is that we may not ever need the real class for
505:             * className; and when we need it, lookupClass() above will deliver it.
506:             */
507:            public static BaseClassInfo lookupClassOrCreatePlaceholder(
508:                    String className, int classLoaderId) {
509:                BaseClassInfo singleExistingClazzOrPCI = null;
510:                BaseClassInfo clazzOrPCI = null;
511:                SameNameClassGroup classGroup = null;
512:                className = className.replace('.', '/').intern(); // NOI18N
513:
514:                Object entry = classes.get(className);
515:
516:                if (entry != null) { // A single class or placeholder, or a group of them for this name, exists
517:
518:                    if (entry instanceof  BaseClassInfo) {
519:                        singleExistingClazzOrPCI = (BaseClassInfo) entry;
520:                        clazzOrPCI = SameNameClassGroup.checkForCompatibility(
521:                                singleExistingClazzOrPCI, classLoaderId);
522:                    } else { // entry is a SameNameClassGroup
523:                        classGroup = (SameNameClassGroup) entry;
524:                        clazzOrPCI = classGroup
525:                                .findCompatibleClass(classLoaderId);
526:                    }
527:
528:                    if (clazzOrPCI != null) { // Found compatible class or placeholder
529:
530:                        return clazzOrPCI;
531:                    } else { // Non-null entry for this class name, but no compatible class or placeholder
532:                        clazzOrPCI = new PlaceholderClassInfo(className,
533:                                classLoaderId);
534:
535:                        if (classGroup != null) {
536:                            classGroup.add(clazzOrPCI);
537:                        } else { // There is already a single incompatible class or placeholder in classes - create a new class group
538:                            classGroup = new SameNameClassGroup();
539:                            classGroup.add(singleExistingClazzOrPCI);
540:                            classGroup.add(clazzOrPCI);
541:                            classes.put(className, classGroup);
542:                        }
543:
544:                        return clazzOrPCI;
545:                    }
546:                } else { // An entry with this name doesn't exist
547:                    clazzOrPCI = new PlaceholderClassInfo(className,
548:                            classLoaderId);
549:                    classes.put(className, clazzOrPCI);
550:
551:                    return clazzOrPCI;
552:                }
553:            }
554:
555:            /**
556:             * Lookup a class in the class repository, only among those currently loaded by the VM.
557:             * If there is no loaded class and allowExistingPlaceholder is true, also check for an existing placeholders.
558:             * Returns either a loaded class, or if allowed an existing placeholder, or null, but not a new placeholder.
559:             */
560:            public static BaseClassInfo lookupLoadedClass(String className,
561:                    int classLoaderId, boolean allowExistingPlaceholder) {
562:                BaseClassInfo singleExistingClazzOrPCI = null;
563:                BaseClassInfo clazzOrPCI = null;
564:                className = className.replace('.', '/').intern(); // NOI18N
565:
566:                Object entry = classes.get(className);
567:
568:                if (entry != null) { // A single class or placeholder, or a group of them for this name, exists
569:
570:                    if (entry instanceof  BaseClassInfo) {
571:                        singleExistingClazzOrPCI = (BaseClassInfo) entry;
572:                        clazzOrPCI = SameNameClassGroup.checkForCompatibility(
573:                                singleExistingClazzOrPCI, classLoaderId);
574:                    } else { // entry is a SameNameClassGroup
575:
576:                        SameNameClassGroup classGroup = (SameNameClassGroup) entry;
577:                        clazzOrPCI = classGroup
578:                                .findCompatibleClass(classLoaderId);
579:                    }
580:
581:                    if (clazzOrPCI != null) { // Found compatible class or placeholder
582:
583:                        if (!(clazzOrPCI instanceof  PlaceholderClassInfo)) {
584:                            return clazzOrPCI;
585:                        } else if (allowExistingPlaceholder) {
586:                            return clazzOrPCI;
587:                        }
588:                    }
589:                }
590:
591:                return null;
592:            }
593:
594:            /**
595:             * Used only for special classes, such as array classes, that don't have a .class file on the class path. If a class
596:             * with the given name does not exist, a BaseClassInfo is created for it immediately.
597:             */
598:            public static BaseClassInfo lookupSpecialClass(String className) {
599:                if (className.indexOf('.') != -1) { // NOI18N
600:                    className = className.replace('.', '/').intern(); // NOI18N
601:                }
602:
603:                BaseClassInfo clazz = (BaseClassInfo) classes.get(className);
604:
605:                if (clazz == null) {
606:                    clazz = new BaseClassInfo(className, 0); // For now, we don't distinguish between Object array classes for different loaders (if such a thing exists)
607:                    classes.put(className, clazz);
608:                }
609:
610:                return clazz;
611:            }
612:
613:            static int getDefiningClassLoaderId(String className,
614:                    int classLoaderId) {
615:                String classId = className + "#" + classLoaderId; // NOI18N
616:                Integer loaderInt = (Integer) definingClassLoaderMap
617:                        .get(classId);
618:
619:                if (loaderInt != null) {
620:                    return loaderInt.intValue();
621:                }
622:
623:                int loader = -1;
624:
625:                try {
626:                    loader = TargetAppRunner.getDefault().getProfilerClient()
627:                            .getDefiningClassLoaderId(className, classLoaderId);
628:                } catch (Exception ex) {
629:                    // Don't bother about reporting an exception - somebody will do that later
630:                }
631:
632:                definingClassLoaderMap.put(classId, new Integer(loader));
633:
634:                return loader;
635:            }
636:
637:            private static CodeRegionBCI getMethodForSourceRegionInNestedClasses(
638:                    ClassInfo clazz, int startLine, int endLine)
639:                    throws ClassNotFoundException, IOException,
640:                    ClassFormatError {
641:                String className = clazz.getName();
642:                String[] nestedClassNames = clazz.getNestedClassNames();
643:                int classNameLen = className.length();
644:
645:                if (nestedClassNames != null) {
646:                    for (int i = 0; i < nestedClassNames.length; i++) {
647:                        if (!(nestedClassNames[i].startsWith(className) && (nestedClassNames[i]
648:                                .length() > classNameLen))) {
649:                            continue;
650:                        }
651:
652:                        try {
653:                            ClassInfo nestedClass = lookupClass(
654:                                    nestedClassNames[i], clazz.getLoaderId());
655:
656:                            if (nestedClass != null) {
657:                                CodeRegionBCI res = getMethodForSourceRegion(
658:                                        nestedClass, startLine, endLine);
659:
660:                                if (res != null) {
661:                                    return res;
662:                                }
663:                            }
664:                        } catch (BadLocationException ex) {
665:                            // Clearly if we got into this method, there was a line number table in the upper level class. So the BadLocationException
666:                            // that can only be thrown if no line number table is found in this particular nested class is a bogus and misleading.
667:                            return null;
668:                        }
669:                    }
670:                }
671:
672:                return null;
673:            }
674:
675:            private static DynamicClassInfo checkForVMSuppliedClass(
676:                    String className, int classLoaderId) throws IOException,
677:                    ClassFormatError {
678:                int realLoaderId = ClassFileCache.getDefault()
679:                        .hasVMSuppliedClassFile(className, classLoaderId);
680:
681:                if (realLoaderId != -1) {
682:                    return new DynamicClassInfo(className, classLoaderId,
683:                            LOCATION_VMSUPPLIED + realLoaderId);
684:                } else {
685:                    return null;
686:                }
687:            }
688:
689:            private static DynamicClassInfo lookupClass(String className,
690:                    int classLoaderId, boolean reportIfNotFound)
691:                    throws IOException, ClassFormatError {
692:                BaseClassInfo singleExistingClazzOrPCI = null;
693:                BaseClassInfo clazzOrPCI = null;
694:                SameNameClassGroup classGroup = null;
695:                className = className.replace('.', '/').intern(); // NOI18N
696:
697:                Object entry = classes.get(className);
698:
699:                if (entry != null) { // A single class or placeholder, or a group of them for this name, exists
700:
701:                    if (entry instanceof  BaseClassInfo) {
702:                        singleExistingClazzOrPCI = (BaseClassInfo) entry;
703:                        clazzOrPCI = SameNameClassGroup.checkForCompatibility(
704:                                singleExistingClazzOrPCI, classLoaderId);
705:                    } else { // entry is a SameNameClassGroup
706:                        classGroup = (SameNameClassGroup) entry;
707:                        clazzOrPCI = classGroup
708:                                .findCompatibleClass(classLoaderId);
709:                    }
710:
711:                    if (clazzOrPCI != null) { // Found compatible class or placeholder
712:
713:                        if (!(clazzOrPCI instanceof  PlaceholderClassInfo)) {
714:                            return (DynamicClassInfo) clazzOrPCI;
715:                        } else { // Found a compatible placeholder
716:
717:                            PlaceholderClassInfo pci = (PlaceholderClassInfo) clazzOrPCI;
718:                            DynamicClassInfo clazz = tryLoadRealClass(
719:                                    className, classLoaderId, reportIfNotFound);
720:
721:                            if (clazz != null) { // Found a real class for this placeholder
722:                                pci.transferDataIntoRealClass(clazz);
723:
724:                                if (classGroup != null) {
725:                                    classGroup.replace(pci, clazz);
726:                                } else {
727:                                    classes.put(className, clazz);
728:                                }
729:
730:                                return clazz;
731:                            } else {
732:                                return null; // Didn't find a real class for this placeholder
733:                            }
734:                        }
735:                    } else { // Non-null entry for this class name, but no compatible class or placeholder
736:
737:                        DynamicClassInfo clazz = tryLoadRealClass(className,
738:                                classLoaderId, reportIfNotFound);
739:
740:                        if (clazz != null) { // Managed to load a right class
741:
742:                            if (classGroup != null) {
743:                                classGroup.add(clazz);
744:                            } else { // There is already a single incompatible class or placeholder in classes - create a new class group
745:                                classGroup = new SameNameClassGroup();
746:                                classGroup.add(singleExistingClazzOrPCI);
747:                                classGroup.add(clazz);
748:                                classes.put(className, classGroup);
749:                            }
750:
751:                            return clazz;
752:                        } else {
753:                            return null; // Could not load a right class
754:                        }
755:                    }
756:                } else { // An entry with this name doesn't exist
757:
758:                    DynamicClassInfo clazz = tryLoadRealClass(className,
759:                            classLoaderId, reportIfNotFound);
760:
761:                    if (clazz != null) {
762:                        classes.put(className, clazz);
763:
764:                        return clazz;
765:                    } else {
766:                        return null;
767:                    }
768:                }
769:            }
770:
771:            private static DynamicClassInfo tryLoadRealClass(String className,
772:                    int classLoaderId, boolean reportIfNotFound)
773:                    throws IOException, ClassFormatError {
774:                DynamicClassInfo clazz = null;
775:                int loader = classLoaderId;
776:
777:                do {
778:                    // In case of remote profiling, even system classes, that we otherwise can look up on disk locally, are
779:                    // supplied by the VM. That's why we always call checkForVMSuppliedClass first.
780:                    clazz = checkForVMSuppliedClass(className, loader);
781:
782:                    if (clazz == null) {
783:                        if (((loader == 0) || (loader == -1))
784:                                && (classPath != null)) { // sanity check; to prevent NPE in case the classPath hasn't been initialized (shouldn't happen anyway)
785:                            clazz = classPath.getClassInfoForClass(className,
786:                                    loader);
787:                        }
788:                    }
789:
790:                    if ((clazz != null) || (loader == 0)) {
791:                        break;
792:                    }
793:
794:                    // Try parent loader - in some cases a class can be initially requested with the loader of its subclass
795:                    loader = ClassLoaderTable.getParentLoader(loader);
796:                } while (loader >= 0);
797:
798:                if (clazz == null) {
799:                    // In some cases, the class loader graph for the app may be a non-tree structure, i.e. one class loader may delegate
800:                    // not just to its parent loader, but to some other loader(s) as well. In that case, our last resort is to ask the
801:                    // initiating loader itself for this class, and then get its defining loader.
802:                    loader = getDefiningClassLoaderId(className, classLoaderId);
803:
804:                    if (loader != -1) {
805:                        clazz = checkForVMSuppliedClass(className, loader); // See above about remote profiling
806:
807:                        if (clazz == null) {
808:                            if (loader == 0) {
809:                                clazz = classPath.getClassInfoForClass(
810:                                        className, loader);
811:                            }
812:                        }
813:                    }
814:                }
815:
816:                if ((clazz == null) && reportIfNotFound) {
817:                    if (!notFoundClasses.contains(className)) {
818:                        MiscUtils.printWarningMessage("class " + className
819:                                + ", ldr = " + classLoaderId
820:                                + " not found anywhere"); // NOI18N
821:                        notFoundClasses.add(className);
822:                    }
823:                }
824:
825:                return clazz;
826:            }
827:
828:            //----------------------------------- Debugging -----------------------------------
829:
830:            /*
831:               private static void dumpLineTable(Method method) {
832:                 LineNumberTable lnt = method.getLineNumberTable();
833:                 if (lnt == null) return;
834:                 LineNumber[] lns = lnt.getLineNumberTable();
835:                 System.out.println("Line number table for " + method.getName() + "." + method.getSignature());
836:                 for (int i = 0; i < lns.length; i++) {
837:                   System.out.println(lns[i].getLineNumber() + " " + lns[i].getStartPC());
838:                 }
839:               }
840:             */
841:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.