Source Code Cross Referenced for RecursiveMethodInstrumentor.java in  » IDE-Netbeans » cvsclient » org » netbeans » lib » profiler » instrumentation » 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.instrumentation 
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.instrumentation;
042:
043:        import org.netbeans.lib.profiler.ProfilerEngineSettings;
044:        import org.netbeans.lib.profiler.classfile.DynamicClassInfo;
045:        import org.netbeans.lib.profiler.classfile.PlaceholderClassInfo;
046:        import org.netbeans.lib.profiler.client.RuntimeProfilingPoint;
047:        import org.netbeans.lib.profiler.global.InstrumentationFilter;
048:        import org.netbeans.lib.profiler.global.ProfilingSessionStatus;
049:        import java.util.ArrayList;
050:        import java.util.Enumeration;
051:        import java.util.Hashtable;
052:
053:        /**
054:         * Base class for two "recursive" method scanners, implementing the "eager" and "lazy" transitive call subgraph revelation and
055:         * instrumentation schemes. This class contains functionality used by both scaners.
056:         *
057:         * @author Tomas Hurka
058:         * @author Misha Dmitriev
059:         * @author Adrian Mos
060:         */
061:        public abstract class RecursiveMethodInstrumentor extends ClassManager {
062:            //~ Inner Classes ------------------------------------------------------------------------------------------------------------
063:
064:            protected static class ReachableMethodPlaceholder extends
065:                    PlaceholderClassInfo {
066:                //~ Instance fields ------------------------------------------------------------------------------------------------------
067:
068:                protected ArrayList methodNamesAndSigs;
069:
070:                //~ Constructors ---------------------------------------------------------------------------------------------------------
071:
072:                ReachableMethodPlaceholder(String className, int classLoaderId) {
073:                    super (className, classLoaderId);
074:                    methodNamesAndSigs = new ArrayList();
075:                }
076:
077:                //~ Methods --------------------------------------------------------------------------------------------------------------
078:
079:                public void registerReachableMethod(String methodName,
080:                        String methodSig) {
081:                    int nameIdx = methodNamesAndSigs.indexOf(methodName);
082:
083:                    if (nameIdx != -1) {
084:                        if (methodNamesAndSigs.get(nameIdx + 1).equals(
085:                                methodSig)) {
086:                            return;
087:                        }
088:                    }
089:
090:                    methodNamesAndSigs.add(methodName);
091:                    methodNamesAndSigs.add(methodSig);
092:                }
093:            }
094:
095:            //~ Instance fields ----------------------------------------------------------------------------------------------------------
096:
097:            protected Hashtable instrClasses = new Hashtable();
098:            protected InstrumentationFilter instrFilter;
099:            protected byte[] codeBytes;
100:            protected boolean dontInstrumentEmptyMethods;
101:            protected boolean dontScanGetterSetterMethods;
102:            protected boolean instrumentClinit;
103:            protected boolean instrumentSpawnedThreads;
104:
105:            // This flag shows whether we have already instrumented the java.lang.reflect.Method.invoke() method to intercept all invocations.
106:            // The current policy is to instrument it eagerly, in the very first method instrumentation packet. However, the actual
107:            // interception can be turned on and off at run time on demand.
108:            protected boolean reflectInvokeInstrumented = false;
109:            protected int markerInjectionType; // Bytecode injections that are set dependent on the above
110:            protected int nInstrClasses;
111:            protected int nInstrMethods;
112:            protected int normalInjectionType; // Bytecode injections that are set dependent on the above
113:            protected int offset;
114:            protected int rootInjectionType; // Bytecode injections that are set dependent on the above
115:            RootMethods rootMethods;
116:
117:            // remembered here because of profiling points
118:            private ProfilerEngineSettings engineSettings;
119:
120:            //~ Constructors -------------------------------------------------------------------------------------------------------------
121:
122:            protected RecursiveMethodInstrumentor(
123:                    ProfilingSessionStatus status,
124:                    ProfilerEngineSettings settings) {
125:                super (status);
126:
127:                switch (status.currentInstrType) {
128:                case INSTR_RECURSIVE_FULL:
129:                    normalInjectionType = INJ_RECURSIVE_NORMAL_METHOD;
130:                    rootInjectionType = INJ_RECURSIVE_ROOT_METHOD;
131:                    markerInjectionType = INJ_RECURSIVE_MARKER_METHOD;
132:
133:                    break;
134:                case INSTR_RECURSIVE_SAMPLED:
135:                    normalInjectionType = INJ_RECURSIVE_SAMPLED_NORMAL_METHOD;
136:                    rootInjectionType = INJ_RECURSIVE_SAMPLED_ROOT_METHOD;
137:                    markerInjectionType = INJ_RECURSIVE_SAMPLED_MARKER_METHOD;
138:
139:                    break;
140:                }
141:
142:                reflectInvokeInstrumented = false;
143:
144:                dontScanGetterSetterMethods = !settings
145:                        .getInstrumentGetterSetterMethods();
146:                dontInstrumentEmptyMethods = !settings
147:                        .getInstrumentEmptyMethods();
148:                instrumentSpawnedThreads = settings
149:                        .getInstrumentSpawnedThreads();
150:                instrFilter = settings.getInstrumentationFilter();
151:                engineSettings = settings;
152:            }
153:
154:            //~ Methods ------------------------------------------------------------------------------------------------------------------
155:
156:            /**
157:             * This method is called when some class containing an instrumentation root method is loaded by the VM (either has just
158:             * been loaded, or the JFluid server, upon the user's command to initiate instrumentation, has detected that it has been
159:             * loaded some time in the past). The JFluid server then sends a RootClassLoadedCommand to the tool. This command contains
160:             * the information on all classes currently loaded by the VM - see the details in this method's header.
161:             * This method should initialize instrumentation-related data structures, register given classes as loaded, and return
162:             * the initial set of methods to instrument in the format given by createInstrumentedMethodPack().
163:             */
164:            abstract Object[] getInitialMethodsToInstrument(
165:                    String[] loadedClasses, int[] loadedClassLoaderIds,
166:                    byte[][] cachedClassFileBytes, RootMethods rootMethods);
167:
168:            public abstract Object[] getMethodsToInstrumentUponClassLoad(
169:                    String className, int classLoaderId,
170:                    boolean threadInCallGraph);
171:
172:            /** Methods below return method bytecodes to instrument upon specific events reported by the JFluid server. */
173:            public abstract Object[] getMethodsToInstrumentUponMethodInvocation(
174:                    String className, int classLoaderId, String methodName,
175:                    String methodSignature);
176:
177:            public abstract Object[] getMethodsToInstrumentUponReflectInvoke(
178:                    String className, int classLoaderId, String methodName,
179:                    String methodSignature);
180:
181:            /** Called every time before a new round of instrumentation, caused by class load, method invoke, etc. */
182:            protected void initInstrMethodData() {
183:                instrClasses.clear();
184:                nInstrClasses = nInstrMethods = 0;
185:                instrumentClinit = false;
186:            }
187:
188:            protected static boolean rootClassNameIsReal(String rootClassName) {
189:                return !rootClassName.equals(NO_CLASS_NAME);
190:            }
191:
192:            protected void addToSubclassList(DynamicClassInfo clazz,
193:                    DynamicClassInfo addedClassInfo) {
194:                String super ClassName = clazz.getSuperclassName();
195:                int loaderId = clazz.getLoaderId();
196:                DynamicClassInfo super Class = javaClassForName(super ClassName,
197:                        loaderId);
198:                clazz.setSuperClass(super Class);
199:
200:                if ((super Class != null) && !clazz.isInterface()) {
201:                    super Class.addSubclass(addedClassInfo);
202:
203:                    if (addedClassInfo != null) {
204:                        findAndMarkOverridingMethodsReachable(super Class,
205:                                addedClassInfo);
206:                    }
207:
208:                    if (super ClassName != "java/lang/Object") {
209:                        addToSubclassList(super Class, addedClassInfo); // NOI18N
210:                    }
211:                }
212:
213:                String[] interfaces = clazz.getInterfaceNames();
214:
215:                if (interfaces != null) {
216:                    for (int i = 0; i < interfaces.length; i++) {
217:                        DynamicClassInfo super Interface = javaClassForName(
218:                                interfaces[i], loaderId);
219:                        clazz.setSuperInterface(super Interface, i);
220:
221:                        if (super Interface != null) {
222:                            super Interface.addSubclass(addedClassInfo);
223:
224:                            if (addedClassInfo != null) {
225:                                findAndMarkOverridingMethodsReachable(
226:                                        super Interface, addedClassInfo);
227:                            }
228:
229:                            addToSubclassList(super Interface, addedClassInfo);
230:                        }
231:                    }
232:                }
233:            }
234:
235:            protected abstract void findAndMarkOverridingMethodsReachable(
236:                    DynamicClassInfo super Class, DynamicClassInfo subClass);
237:
238:            protected abstract void processInvoke(DynamicClassInfo clazz,
239:                    boolean virtualCall, int index);
240:
241:            protected final int at(int index) {
242:                return codeBytes[offset + index] & 0xFF;
243:            }
244:
245:            /**
246:             * Given the table at the specified index, return the specified entry
247:             */
248:            protected final long intAt(int tbl, int entry) {
249:                int base = tbl + (entry << 2);
250:
251:                return (codeBytes[base] << 24)
252:                        | ((codeBytes[base + 1] & 0xFF) << 16)
253:                        | ((codeBytes[base + 2] & 0xFF) << 8)
254:                        | (codeBytes[base + 3] & 0xFF);
255:            }
256:
257:            protected void scanMethod(DynamicClassInfo clazz, int index) {
258:                byte[] bytecode = clazz.getMethodBytecode(index);
259:                scanBytecode(clazz, bytecode);
260:            }
261:
262:            protected final int shortAt(int index) {
263:                int base = offset + index;
264:
265:                return ((codeBytes[base] & 0xFF) << 8)
266:                        | (codeBytes[base + 1] & 0xFF);
267:            }
268:
269:            /**
270:             * This method is used either to normally process the bytecodes of a method, in which case clazz != null and the return
271:             * result is ignored. If clazz == null, then returns false upon encountering the first invoke bytecode, and true if there
272:             * are no invokes, i.e. it's a leaf method.
273:             */
274:            protected boolean scanBytecode(DynamicClassInfo clazz, byte[] code) {
275:                codeBytes = code;
276:
277:                for (offset = 0; offset < codeBytes.length;) {
278:                    int opcode = at(0);
279:
280:                    if (opcode == opc_wide) {
281:                        opcode = at(1);
282:
283:                        if (((opcode >= opc_iload) && (opcode <= opc_aload))
284:                                || ((opcode >= opc_istore) && (opcode <= opc_astore))
285:                                || (opcode == opc_ret)) {
286:                            offset += 4;
287:                        } else if (opcode == opc_iinc) {
288:                            offset += 6;
289:                        } else {
290:                            offset++;
291:                        }
292:                    } else {
293:                        switch (opcode) {
294:                        case opc_tableswitch: {
295:                            int tbl = (offset + 1 + 3) & (~3); // four byte boundry
296:                            long default_skip = intAt(tbl, 0);
297:                            long low = intAt(tbl, 1);
298:                            long high = intAt(tbl, 2);
299:                            tbl += (3 << 2); // three int header
300:                            offset = tbl + (int) ((high - low + 1) << 2);
301:
302:                            break;
303:                        }
304:                        case opc_lookupswitch: {
305:                            int tbl = (offset + 1 + 3) & (~3); // four byte boundry
306:                            long default_skip = intAt(tbl, 0);
307:                            int npairs = (int) intAt(tbl, 1);
308:                            int nints = npairs * 2;
309:                            tbl += (2 << 2); // two int header
310:                            offset = tbl + (nints << 2);
311:
312:                            break;
313:                        }
314:                        case opc_invokevirtual:
315:                        case opc_invokespecial:
316:                        case opc_invokestatic: {
317:                            if (clazz == null) {
318:                                return false; // Using scanBytecode() as a leaf-method checker
319:                            }
320:
321:                            int index = shortAt(1);
322:                            processInvoke(clazz, (opcode == opc_invokevirtual),
323:                                    index);
324:                            offset += 3;
325:
326:                            break;
327:                        }
328:                        case opc_invokeinterface: {
329:                            if (clazz == null) {
330:                                return false; // Using scanBytecode() as a leaf-method checker
331:                            }
332:
333:                            int index = shortAt(1);
334:                            processInvoke(clazz, true, index);
335:                            offset += 5;
336:
337:                            break;
338:                        }
339:                        default:
340:                            offset += opc_length[opcode];
341:
342:                            break;
343:                        }
344:                    }
345:                }
346:
347:                return true;
348:            }
349:
350:            protected abstract boolean tryInstrumentSpawnedThreads(
351:                    DynamicClassInfo clazz);
352:
353:            protected static boolean isEmptyMethod(byte[] code) {
354:                return (code.length == 1); // Can't be anything but "return"
355:            }
356:
357:            protected static boolean isGetterSetterMethod(byte[] code) {
358:                // Getter (accessor) method:
359:                // 0 aload_0; 1 getfield x ; 4 (i..a)return.  Parameter size = 1
360:                // Setter method:
361:                // 0 aload_0; 1 (i..a)load_1; 2 putfield x; 5 return. Parameter size = 2
362:                if (code.length == 5) {
363:                    if (((code[0] & 0xFF) == opc_aload_0)
364:                            && ((code[1] & 0xFF) == opc_getfield)
365:                            && (((code[4] & 0xFF) >= opc_ireturn) && ((code[4] & 0xFF) <= opc_areturn))) {
366:                        return true;
367:                    }
368:                } else if (code.length == 6) {
369:                    if (((code[0] & 0xFF) == opc_aload_0)
370:                            && (((code[1] & 0xFF) >= opc_iload_1) && ((code[1] & 0xFF) <= opc_aload_1))
371:                            && ((code[2] & 0xFF) == opc_putfield)
372:                            && ((code[5] & 0xFF) == opc_return)) {
373:                        return true;
374:                    }
375:                }
376:
377:                return false;
378:            }
379:
380:            protected boolean isLeafMethod(byte[] code) {
381:                return scanBytecode(null, code);
382:            }
383:
384:            /** Create a multi-class packet of instrumented methods or classes */
385:            protected Object[] createInstrumentedMethodPack() {
386:                if (nInstrMethods == 0) {
387:                    return null;
388:                }
389:
390:                return createInstrumentedMethodPack15();
391:            }
392:
393:            /** Create a single-class packet of instrumented methods or classes in response to a class load event. */
394:            protected Object[] createInstrumentedMethodPack(
395:                    DynamicClassInfo clazz) {
396:                if (nInstrMethods == 0) {
397:                    return null;
398:                }
399:
400:                if (clazz.isInterface()) {
401:                    return null;
402:                }
403:
404:                return createInstrumentedMethodPack15(clazz);
405:            }
406:
407:            protected void markAllMethodsMarker(DynamicClassInfo clazz) {
408:                clazz.setAllMethodsMarkers();
409:            }
410:
411:            protected void markAllMethodsRoot(DynamicClassInfo clazz) {
412:                clazz.setAllMethodsRoots();
413:            }
414:
415:            protected void markClassAndMethodForInstrumentation(
416:                    DynamicClassInfo clazz, int methodIdx) {
417:                if ((status.getStartingMethodId() + nInstrMethods) < 65535) {
418:                    String classNameAndLoader = clazz.getNameAndLoader();
419:
420:                    if (!instrClasses.containsKey(classNameAndLoader)) {
421:                        instrClasses.put(classNameAndLoader, clazz);
422:                        nInstrClasses++;
423:                    }
424:
425:                    nInstrMethods++;
426:                } else { // Can't instrument more than 64K methods - mark this method as already instrumented
427:                    clazz.setMethodInstrumented(methodIdx);
428:                }
429:            }
430:
431:            protected boolean markMethod(DynamicClassInfo clazz, int rootMethod) {
432:                String rootMethodName = rootMethods.methodNames[rootMethod];
433:                String rootMethodSignature = rootMethods.methodSignatures[rootMethod];
434:                boolean isMarkerMethod = rootMethods.markerMethods[rootMethod];
435:                int rootMethodIdx = clazz.getMethodIndex(rootMethodName,
436:                        rootMethodSignature);
437:
438:                if (rootMethodIdx == -1) {
439:                    return false;
440:                }
441:
442:                if (isMarkerMethod) {
443:                    clazz.setMethodMarker(rootMethodIdx);
444:                } else {
445:                    clazz.setMethodRoot(rootMethodIdx);
446:                }
447:
448:                return true;
449:            }
450:
451:            protected boolean markMethodMarker(DynamicClassInfo clazz,
452:                    String rootMethodName, String rootMethodSignature) {
453:                int rootMethodIdx = clazz.getMethodIndex(rootMethodName,
454:                        rootMethodSignature);
455:
456:                if (rootMethodIdx == -1) {
457:                    return false;
458:                }
459:
460:                clazz.setMethodMarker(rootMethodIdx);
461:
462:                return true;
463:            }
464:
465:            protected boolean markMethodRoot(DynamicClassInfo clazz,
466:                    String rootMethodName, String rootMethodSignature) {
467:                int rootMethodIdx = clazz.getMethodIndex(rootMethodName,
468:                        rootMethodSignature);
469:
470:                if (rootMethodIdx == -1) {
471:                    return false;
472:                }
473:
474:                clazz.setMethodRoot(rootMethodIdx);
475:
476:                return true;
477:            }
478:
479:            protected boolean matchesWildcard(String wildcard,
480:                    String loadedClassName) {
481:                //    System.err.println("Matches wildcard: "+loadedClassName+", wild: "+wildcard + " : " + (loadedClassName.startsWith(wildcard) && (loadedClassName.indexOf('/', wildcard.length()) == -1)));
482:                return loadedClassName.startsWith(wildcard)
483:                        && (loadedClassName.indexOf('/', wildcard.length()) == -1); // NOI18N
484:            }
485:
486:            //---------------------------- Private implementation of instrumentation data packing ---------------------------
487:
488:            /** Create a multi-class packet of instrumented 1.5-style data */
489:            private Object[] createInstrumentedMethodPack15() {
490:                int reflectMethodClassIdx = -1;
491:
492:                if (!reflectInvokeInstrumented) {
493:                    // Check if java.lang.reflect.Method is already among classes to instrument
494:                    int idx = 0;
495:
496:                    for (Enumeration e = instrClasses.elements(); e
497:                            .hasMoreElements(); idx++) {
498:                        DynamicClassInfo clazz = (DynamicClassInfo) e
499:                                .nextElement();
500:
501:                        if (clazz.getName() == JAVA_LANG_REFLECT_METHOD_SLASHED_CLASS_NAME) {
502:                            reflectMethodClassIdx = idx;
503:
504:                            break;
505:                        }
506:                    }
507:
508:                    if (reflectMethodClassIdx == -1) {
509:                        nInstrClasses++;
510:                    }
511:                }
512:
513:                String[] instrMethodClasses = new String[nInstrClasses];
514:                int[] instrClassLoaderIds = new int[nInstrClasses];
515:                boolean[] instrMethodLeaf = new boolean[nInstrMethods];
516:                byte[][] replacementClassFileBytes = new byte[nInstrClasses][];
517:                int methodId = status.getStartingMethodId();
518:                int classIdx = 0;
519:                int methodIdx = 0;
520:
521:                for (Enumeration e = instrClasses.elements(); e
522:                        .hasMoreElements();) {
523:                    DynamicClassInfo clazz = (DynamicClassInfo) e.nextElement();
524:                    int nMethods = clazz.getMethodNames().length;
525:                    instrMethodClasses[classIdx] = clazz.getName().replace('/',
526:                            '.').intern(); // NOI18N
527:
528:                    boolean hasRootMethods = clazz
529:                            .hasUninstrumentedRootMethods();
530:                    boolean hasMarkerMethods = clazz
531:                            .hasUninstrumentedMarkerMethods();
532:                    DynamicConstantPoolExtension.getCPFragment(clazz,
533:                            normalInjectionType);
534:
535:                    if (hasRootMethods) {
536:                        DynamicConstantPoolExtension.getCPFragment(clazz,
537:                                rootInjectionType);
538:                    }
539:
540:                    if (hasMarkerMethods) {
541:                        DynamicConstantPoolExtension.getCPFragment(clazz,
542:                                markerInjectionType);
543:                    }
544:
545:                    int imInClass = 0;
546:                    byte[][] replacementMethodInfos = new byte[nMethods][];
547:                    RuntimeProfilingPoint[] pointsForClass = getRuntimeProfilingPoints(
548:                            engineSettings.getRuntimeProfilingPoints(), clazz);
549:
550:                    //System.err.println("CLazz: "+clazz.getName());
551:                    for (int i = 0; i < nMethods; i++) {
552:                        // FIXME: issue 68840: An overriden method overriding with subclass of return type is instrumented twice
553:                        // http://profiler.netbeans.org/issues/show_bug.cgi?id=68840
554:                        // a method whose return type is not exact match as the method which it implements/overrides would be listed
555:                        // and processed twice, leading to double instrumentation
556:
557:                        //System.err.println("Method: "+clazz.getMethodName(i)+" " + clazz.getMethodSignature(i));
558:                        RuntimeProfilingPoint[] points = getRuntimeProfilingPoints(
559:                                pointsForClass, i);
560:
561:                        if (!clazz.isMethodInstrumented(i)) {
562:                            if (clazz.isMethodReachable(i)
563:                                    && !clazz.isMethodUnscannable(i)) {
564:                                clazz.setMethodInstrumented(i);
565:                                instrMethodLeaf[methodIdx] = clazz
566:                                        .isMethodLeaf(i);
567:                                //System.err.println(">>>1 For method " + clazz.getName() + "." + clazz.getMethodName(i) + clazz.getMethodSignature(i) + " gonna use methodId = " + methodId);
568:                                replacementMethodInfos[i] = InstrumentationFactory
569:                                        .instrumentMethod(clazz, i,
570:                                                normalInjectionType,
571:                                                rootInjectionType,
572:                                                markerInjectionType,
573:                                                methodId++, points);
574:                                clazz.saveMethodInfo(i,
575:                                        replacementMethodInfos[i]);
576:
577:                                status.updateInstrMethodsInfo(
578:                                        instrMethodClasses[classIdx], clazz
579:                                                .getLoaderId(), clazz
580:                                                .getMethodNames()[i], clazz
581:                                                .getMethodSignatures()[i]);
582:                                imInClass++;
583:                                methodIdx++;
584:                            } else if (points.length > 0) {
585:                                replacementMethodInfos[i] = InstrumentationFactory
586:                                        .instrumentAsProiflePointHitMethod(
587:                                                clazz, i, normalInjectionType,
588:                                                points);
589:                                clazz.saveMethodInfo(i,
590:                                        replacementMethodInfos[i]);
591:                            }
592:                        } else {
593:                            replacementMethodInfos[i] = clazz.getMethodInfo(i); // Will return the previously instrumented methodInfo
594:                            imInClass++;
595:                        }
596:                    }
597:
598:                    instrumentServletDoMethods(clazz, replacementMethodInfos);
599:
600:                    if (imInClass > 0) {
601:                        if (hasRootMethods) {
602:                            clazz.setHasUninstrumentedRootMethods(false);
603:                        }
604:
605:                        if (hasMarkerMethods) {
606:                            clazz.setHasUninstrumentedMarkerMethods(false);
607:                        }
608:
609:                        DynamicConstantPoolExtension wholeECP = DynamicConstantPoolExtension
610:                                .getAllAddedCPFragments(clazz);
611:                        int nAddedCPEntries = wholeECP.getNEntries();
612:                        byte[] addedCPContents = wholeECP.getContents();
613:                        replacementClassFileBytes[classIdx] = ClassRewriter
614:                                .rewriteClassFile(clazz,
615:                                        replacementMethodInfos,
616:                                        nAddedCPEntries, addedCPContents);
617:                    }
618:
619:                    instrClassLoaderIds[classIdx] = clazz.getLoaderId();
620:                    classIdx++;
621:                }
622:
623:                if (!reflectInvokeInstrumented) { // Special instrumentation of java.lang.reflect.Method.invoke()
624:
625:                    DynamicClassInfo clazz = javaClassForName(
626:                            JAVA_LANG_REFLECT_METHOD_DOTTED_CLASS_NAME, 0);
627:                    int nMethods = clazz.getMethodNames().length;
628:                    byte[][] replacementMethodInfos = new byte[nMethods][];
629:
630:                    if (reflectMethodClassIdx == -1) {
631:                        instrMethodClasses[classIdx] = JAVA_LANG_REFLECT_METHOD_DOTTED_CLASS_NAME;
632:                        instrClassLoaderIds[classIdx] = 0;
633:                    } else {
634:                        classIdx = reflectMethodClassIdx;
635:
636:                        for (int i = 0; i < nMethods; i++) {
637:                            replacementMethodInfos[i] = clazz.getMethodInfo(i);
638:                        }
639:                    }
640:
641:                    int idx = clazz.getMethodIndex(INVOKE_METHOD_NAME,
642:                            INVOKE_METHOD_SIGNATURE);
643:                    DynamicConstantPoolExtension.getCPFragment(clazz,
644:                            INJ_REFLECT_METHOD_INVOKE);
645:
646:                    replacementMethodInfos[idx] = InstrumentationFactory
647:                            .instrumentAsReflectInvokeMethod(clazz, idx);
648:
649:                    DynamicConstantPoolExtension wholeECP = DynamicConstantPoolExtension
650:                            .getAllAddedCPFragments(clazz);
651:                    int nAddedCPEntries = wholeECP.getNEntries();
652:                    byte[] addedCPContents = wholeECP.getContents();
653:                    replacementClassFileBytes[classIdx] = ClassRewriter
654:                            .rewriteClassFile(clazz, replacementMethodInfos,
655:                                    nAddedCPEntries, addedCPContents);
656:
657:                    clazz.saveMethodInfo(idx, replacementMethodInfos[idx]);
658:                    reflectInvokeInstrumented = true;
659:                }
660:
661:                return new Object[] { instrMethodClasses, instrClassLoaderIds,
662:                        instrMethodLeaf, replacementClassFileBytes };
663:            }
664:
665:            /** Create a single-class packet of instrumented 1.5-style data */
666:            private Object[] createInstrumentedMethodPack15(
667:                    DynamicClassInfo clazz) {
668:                String[] methodNames = clazz.getMethodNames();
669:
670:                String[] instrMethodClasses = new String[1];
671:                int[] instrClassLoaderIds = new int[] { clazz.getLoaderId() };
672:                String className = clazz.getName().replace('/', '.').intern(); // NOI18N
673:                instrMethodClasses[0] = className;
674:
675:                boolean[] instrMethodLeaf = new boolean[nInstrMethods];
676:                int methodId = status.getStartingMethodId();
677:                int methodIdx = 0;
678:
679:                boolean hasRootMethods = clazz.hasUninstrumentedRootMethods();
680:                boolean hasMarkerMethods = clazz
681:                        .hasUninstrumentedMarkerMethods();
682:                boolean isReflectMethodClass = clazz.getName() == JAVA_LANG_REFLECT_METHOD_SLASHED_CLASS_NAME;
683:                DynamicConstantPoolExtension.getCPFragment(clazz,
684:                        normalInjectionType);
685:
686:                if (hasRootMethods) {
687:                    DynamicConstantPoolExtension.getCPFragment(clazz,
688:                            rootInjectionType);
689:                }
690:
691:                if (hasMarkerMethods) {
692:                    DynamicConstantPoolExtension.getCPFragment(clazz,
693:                            markerInjectionType);
694:                }
695:
696:                byte[][] replacementMethodInfos = new byte[methodNames.length][];
697:                RuntimeProfilingPoint[] pointsForClass = getRuntimeProfilingPoints(
698:                        engineSettings.getRuntimeProfilingPoints(), clazz);
699:
700:                for (int i = 0; i < methodNames.length; i++) {
701:                    RuntimeProfilingPoint[] points = getRuntimeProfilingPoints(
702:                            pointsForClass, i);
703:
704:                    if (!clazz.isMethodInstrumented(i)) {
705:                        if ((clazz.isMethodReachable(i) && !clazz
706:                                .isMethodUnscannable(i))
707:                                || (instrumentClinit && (methodNames[i] == "<clinit>"))) { // NOI18N
708:                            clazz.setMethodInstrumented(i);
709:                            instrMethodLeaf[methodIdx++] = clazz
710:                                    .isMethodLeaf(i);
711:                            //System.err.println("!!!>>>2 For method " + clazz.getName() + "." + clazz.getMethodName(i) + clazz.getMethodSignature(i) + " gonna use methodId = " + methodId);
712:                            replacementMethodInfos[i] = InstrumentationFactory
713:                                    .instrumentMethod(clazz, i,
714:                                            normalInjectionType,
715:                                            rootInjectionType,
716:                                            markerInjectionType, methodId++,
717:                                            points);
718:                            clazz.saveMethodInfo(i, replacementMethodInfos[i]);
719:                            status.updateInstrMethodsInfo(
720:                                    instrMethodClasses[0], clazz.getLoaderId(),
721:                                    clazz.getMethodNames()[i], clazz
722:                                            .getMethodSignatures()[i]);
723:                        } else if (points.length > 0) {
724:                            replacementMethodInfos[i] = InstrumentationFactory
725:                                    .instrumentAsProiflePointHitMethod(clazz,
726:                                            i, normalInjectionType, points);
727:                            clazz.saveMethodInfo(i, replacementMethodInfos[i]);
728:                        }
729:                    } else {
730:                        replacementMethodInfos[i] = clazz.getMethodInfo(i); // Will return the previously instrumented methodInfo
731:                    }
732:                }
733:
734:                instrumentServletDoMethods(clazz, replacementMethodInfos);
735:
736:                if (hasRootMethods) {
737:                    clazz.setHasUninstrumentedRootMethods(false);
738:                }
739:
740:                if (hasMarkerMethods) {
741:                    clazz.setHasUninstrumentedMarkerMethods(false);
742:                }
743:
744:                DynamicConstantPoolExtension wholeECP = DynamicConstantPoolExtension
745:                        .getAllAddedCPFragments(clazz);
746:                int nAddedCPEntries = wholeECP.getNEntries();
747:                byte[] addedCPContents = wholeECP.getContents();
748:                byte[] replacementClassFile = ClassRewriter.rewriteClassFile(
749:                        clazz, replacementMethodInfos, nAddedCPEntries,
750:                        addedCPContents);
751:
752:                return new Object[] { instrMethodClasses, instrClassLoaderIds,
753:                        instrMethodLeaf, new byte[][] { replacementClassFile } };
754:            }
755:
756:            private void instrumentServletDoMethods(DynamicClassInfo clazz,
757:                    byte[][] replacementMethodInfos) {
758:                if (!Boolean
759:                        .getBoolean("org.netbeans.lib.profiler.servletTracking")) { // NOI18N
760:
761:                    return;
762:                }
763:
764:                if (clazz.isServletDoMethodScanned()) {
765:                    return;
766:                }
767:
768:                clazz.setServletDoMethodScanned();
769:
770:                if (!clazz.isSubclassOf(HandleServletDoMethodCallInjector
771:                        .getClassName())) {
772:                    return;
773:                }
774:
775:                DynamicConstantPoolExtension.getCPFragment(clazz,
776:                        INJ_SERVLET_DO_METHOD);
777:
778:                String[] methods = HandleServletDoMethodCallInjector
779:                        .getMethodNames();
780:                String[] sigs = HandleServletDoMethodCallInjector
781:                        .getMethodSignatures();
782:
783:                for (int i = 0; i < methods.length; i++) {
784:                    int midx = clazz.getMethodIndex(methods[i], sigs[i]);
785:
786:                    if (midx != -1) {
787:                        replacementMethodInfos[midx] = InstrumentationFactory
788:                                .instrumentAsServletDoMethod(clazz, midx);
789:                        clazz
790:                                .saveMethodInfo(midx,
791:                                        replacementMethodInfos[midx]);
792:                    }
793:                }
794:            }
795:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.