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


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         * The Original Software is NetBeans. The Initial Developer of the Original
0026:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0027:         * Microsystems, Inc. All Rights Reserved.
0028:         *
0029:         * If you wish your version of this file to be governed by only the CDDL
0030:         * or only the GPL Version 2, indicate your decision by adding
0031:         * "[Contributor] elects to include this software in this distribution
0032:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0033:         * single choice of license, a recipient has the option to distribute
0034:         * your version of this file under either the CDDL, the GPL Version 2 or
0035:         * to extend the choice of license to its licensees as provided above.
0036:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0037:         * Version 2 license, then the option applies only if the new code is
0038:         * made subject to such option by the copyright holder.
0039:         */
0040:
0041:        package org.netbeans.lib.profiler;
0042:
0043:        import org.netbeans.lib.profiler.classfile.ClassRepository;
0044:        import org.netbeans.lib.profiler.client.AppStatusHandler;
0045:        import org.netbeans.lib.profiler.client.ClientUtils;
0046:        import org.netbeans.lib.profiler.client.MonitoredData;
0047:        import org.netbeans.lib.profiler.global.CalibrationDataFileIO;
0048:        import org.netbeans.lib.profiler.global.CommonConstants;
0049:        import org.netbeans.lib.profiler.global.Platform;
0050:        import org.netbeans.lib.profiler.global.ProfilingSessionStatus;
0051:        import org.netbeans.lib.profiler.instrumentation.BadLocationException;
0052:        import org.netbeans.lib.profiler.instrumentation.InstrumentationException;
0053:        import org.netbeans.lib.profiler.instrumentation.Instrumentor;
0054:        import org.netbeans.lib.profiler.marker.Marker;
0055:        import org.netbeans.lib.profiler.results.EventBufferProcessor;
0056:        import org.netbeans.lib.profiler.results.EventBufferResultsProvider;
0057:        import org.netbeans.lib.profiler.results.ProfilingResultsDispatcher;
0058:        import org.netbeans.lib.profiler.results.coderegion.CodeRegionResultsSnapshot;
0059:        import org.netbeans.lib.profiler.results.cpu.CPUCCTProvider;
0060:        import org.netbeans.lib.profiler.results.cpu.CPUResultsSnapshot;
0061:        import org.netbeans.lib.profiler.results.cpu.FlatProfileProvider;
0062:        import org.netbeans.lib.profiler.results.cpu.cct.CCTResultsFilter;
0063:        import org.netbeans.lib.profiler.results.cpu.cct.TimeCollector;
0064:        import org.netbeans.lib.profiler.results.memory.*;
0065:        import org.netbeans.lib.profiler.utils.MiscUtils;
0066:        import org.netbeans.lib.profiler.utils.StringUtils;
0067:        import org.netbeans.lib.profiler.wireprotocol.*;
0068:        import java.awt.EventQueue;
0069:        import java.io.IOException;
0070:        import java.io.ObjectInputStream;
0071:        import java.io.ObjectOutputStream;
0072:        import java.lang.reflect.InvocationTargetException;
0073:        import java.net.ConnectException;
0074:        import java.net.Socket;
0075:        import java.text.MessageFormat;
0076:        import java.util.*;
0077:
0078:        /**
0079:         * The interface between the tool and the profiling back end.
0080:         *
0081:         * @author Tomas Hurka
0082:         * @author Misha Dmitriev
0083:         * @author Adrian Mos
0084:         * @author Ian Formanek
0085:         */
0086:        public class ProfilerClient implements  CommonConstants {
0087:            //~ Inner Classes ------------------------------------------------------------------------------------------------------------
0088:
0089:            /**
0090:             * Thread for execution of commands that, due to limitations of our wire protocol, need to be executed such that
0091:             * the ServerListener thread doesn't stay blocked while these commands are executed. See executeInSeparateThread()
0092:             * above.
0093:             */
0094:            private class SeparateCmdExecutionThread extends Thread {
0095:                //~ Methods --------------------------------------------------------------------------------------------------------------
0096:
0097:                public void run() {
0098:                    setName(PROFILER_SEPARATE_EXEC_THREAD_NAME); // NOI18N
0099:
0100:                    synchronized (execInSeparateThreadLock) {
0101:                        while (true) {
0102:                            try {
0103:                                execInSeparateThreadLock.wait();
0104:                            } catch (InterruptedException ex) {
0105:                                MiscUtils
0106:                                        .internalError("ProfilerClient.SpecialExecutionThread.run()"); // NOI18N
0107:                            }
0108:
0109:                            if (execInSeparateThreadCmd == null) {
0110:                                return; // It was a signal to this thread to terminate (currently not used, though)
0111:                            }
0112:
0113:                            Command cmd = execInSeparateThreadCmd;
0114:                            execInSeparateThreadCmd = null;
0115:
0116:                            switch (cmd.getType()) {
0117:                            case Command.ROOT_CLASS_LOADED:
0118:                                instrumentMethodGroupFromRoot((RootClassLoadedCommand) cmd);
0119:
0120:                                //instrMethodGroupFromRootComplete = true;
0121:                                break;
0122:                            case Command.CLASS_LOADED:
0123:                            case Command.METHOD_INVOKED_FIRST_TIME:
0124:                            case Command.METHOD_LOADED:
0125:                                instrumentMethodGroupFollowUp(cmd);
0126:
0127:                                break;
0128:                            case Command.EVENT_BUFFER_DUMPED:
0129:
0130:                                int bufSize = ((EventBufferDumpedCommand) cmd)
0131:                                        .getBufSize();
0132:                                EventBufferProcessor
0133:                                        .readDataAndPrepareForProcessing(bufSize);
0134:
0135:                                List profilePointHits = new ArrayList();
0136:                                EventBufferResultsProvider.getDefault()
0137:                                        .dataReady(bufSize,
0138:                                                getCurrentInstrType());
0139:                                //              processProfilingResults(bufSize, profilePointHits);
0140:                                //              profilePointHit(profilePointHits);
0141:                                sendSimpleRespToServer(true, null);
0142:
0143:                                break;
0144:                            case Command.CLASS_LOADER_UNLOADING:
0145:
0146:                                // We have to grab the forceObtainedResultsDumpLock to prevent forceObtainedResultsDump() coming in while
0147:                                // we are processing the data, sending the request for dump to the server that currently awaits the
0148:                                // request for jmethodIds, and thus creating a "distributed deadlock".
0149:                                synchronized (ProfilerClient.this ) {
0150:                                    synchronized (forceObtainedResultsDumpLock) {
0151:                                        if (memCctProvider != null) {
0152:                                            memCctProvider.updateInternals();
0153:                                        }
0154:
0155:                                        sendSimpleRespToServer(true, null);
0156:                                    }
0157:                                }
0158:
0159:                                break;
0160:                            }
0161:                        }
0162:                    }
0163:                }
0164:            }
0165:
0166:            private class ServerListener extends Thread {
0167:                //~ Instance fields ------------------------------------------------------------------------------------------------------
0168:
0169:                private final Object startedFlagLock = new Object();
0170:
0171:                // @GuardedBy startedFlagLock
0172:                private int startedFlag = 0; // 0 = initial state; 1 = started; -1 = cancelled
0173:
0174:                //~ Methods --------------------------------------------------------------------------------------------------------------
0175:
0176:                public boolean isRunning() {
0177:                    synchronized (startedFlagLock) {
0178:                        return startedFlag == 1;
0179:                    }
0180:                }
0181:
0182:                public void cancel() {
0183:                    synchronized (startedFlagLock) {
0184:                        startedFlag = -1;
0185:                        startedFlagLock.notifyAll();
0186:                    }
0187:                }
0188:
0189:                public void run() {
0190:                    // Wait until we know that the connection is open
0191:                    synchronized (startedFlagLock) {
0192:                        while (startedFlag == 0) { // while the state hasn't been explicitly changed
0193:
0194:                            try {
0195:                                startedFlagLock.wait(500);
0196:                            } catch (InterruptedException e) {
0197:                                startedFlag = -1; // thread has been interrupet = effectively cancelled
0198:                            }
0199:                        }
0200:
0201:                        if (startedFlag == -1) { // cancelled
0202:
0203:                            return;
0204:                        }
0205:                    }
0206:
0207:                    while (targetVMAlive) {
0208:                        try {
0209:                            Object o = wireIO.receiveCommandOrResponse();
0210:
0211:                            //System.out.println(">>> Got response or command from server " + o);
0212:                            if (o == null) {
0213:                                closeConnection();
0214:                            } else {
0215:                                if (o instanceof  Command) {
0216:                                    handleServerCommand((Command) o);
0217:                                } else {
0218:                                    setLastResponse((Response) o);
0219:                                }
0220:                            }
0221:                        } catch (IOException ex) {
0222:                            if (targetVMAlive
0223:                                    && !terminateOrDetachCommandIssued) { // It wasn't a normal connection shutdown
0224:                                MiscUtils
0225:                                        .printErrorMessage("exception while trying to get response from the target JVM:\n"
0226:                                                + ex); // NOI18N
0227:                                closeConnection();
0228:
0229:                                //            serverCommandHandler.handleServerCommand(null); // does not seem to do anything
0230:                            }
0231:                        }
0232:                    }
0233:                }
0234:
0235:                public void shutdown() {
0236:                    synchronized (startedFlagLock) {
0237:                        startedFlag = 0;
0238:                        startedFlagLock.notifyAll();
0239:                    }
0240:                }
0241:
0242:                public void startRunning() {
0243:                    synchronized (startedFlagLock) {
0244:                        startedFlag = 1;
0245:                        startedFlagLock.notifyAll();
0246:                    }
0247:                }
0248:
0249:                private void handleServerCommand(final Command cmd) {
0250:                    switch (cmd.getType()) {
0251:                    case Command.SHUTDOWN_INITIATED:
0252:                        status.targetAppRunning = false;
0253:
0254:                        // Get and save the latest results and the internal statistics before the target VM goes away
0255:                        (new Thread() {
0256:                            public void run() {
0257:                                try {
0258:                                    int instrType = getCurrentInstrType();
0259:
0260:                                    if (currentInstrTypeIsRecursiveCPUProfiling()
0261:                                            || currentInstrTypeIsMemoryProfiling()) {
0262:                                        forceObtainedResultsDump();
0263:                                    }
0264:
0265:                                    // In case of memory profiling, fetch additional data from the VM - names for all jmethodIDs and
0266:                                    // object count
0267:                                    if (currentInstrTypeIsMemoryProfiling()) {
0268:                                        savedAllocatedObjectsCountResults = getAllocatedObjectsCountResults();
0269:
0270:                                        //                  if (mcgb != null) {
0271:                                        //                    mcgb.getNamesForJMethodIds();
0272:                                        //                  }
0273:                                    }
0274:
0275:                                    status.savedInternalStats = getInternalStats();
0276:
0277:                                    appStatusHandler.handleShutdown();
0278:
0279:                                    sendSimpleCmdToServer(Command.SHUTDOWN_OK);
0280:                                } catch (ClientUtils.TargetAppOrVMTerminated ex) { /* Ignore silently */
0281:                                }
0282:                            }
0283:                        }).start();
0284:
0285:                        break;
0286:                    case Command.SHUTDOWN_COMPLETED:
0287:                        targetVMAlive = false;
0288:                        status.targetAppRunning = false;
0289:                        EventBufferProcessor.removeEventBufferFile();
0290:
0291:                        break;
0292:                    case Command.ROOT_CLASS_LOADED:
0293:                        executeInSeparateThread(cmd);
0294:
0295:                        break;
0296:                    case Command.CLASS_LOADED:
0297:                    case Command.METHOD_INVOKED_FIRST_TIME:
0298:                    case Command.METHOD_LOADED:
0299:                        executeInSeparateThread(cmd);
0300:
0301:                        break;
0302:                    case Command.EVENT_BUFFER_DUMPED:
0303:                        readAndProcessProfilingResults((EventBufferDumpedCommand) cmd);
0304:
0305:                        break;
0306:                    case Command.CLASS_LOADER_UNLOADING:
0307:                        executeInSeparateThread(cmd);
0308:
0309:                        break;
0310:                    case Command.RESULTS_AVAILABLE:
0311:                        resultsStart = System.currentTimeMillis();
0312:
0313:                        break;
0314:                    case Command.GET_CLASSID:
0315:
0316:                        GetClassIdCommand cidCmd = (GetClassIdCommand) cmd;
0317:                        int classId = instrumentor.getClassId(cidCmd
0318:                                .getClassName(), cidCmd.getClassLoaderId());
0319:                        sendComplexRespToServer(new GetClassIdResponse(
0320:                                classId != -1, classId));
0321:
0322:                        break;
0323:                    case Command.STILL_ALIVE:
0324:                        break;
0325:                    }
0326:
0327:                    if (!targetVMAlive) {
0328:                        closeConnection();
0329:                    }
0330:
0331:                    serverCommandHandler.handleServerCommand(cmd);
0332:                }
0333:            }
0334:
0335:            //~ Static fields/initializers -----------------------------------------------------------------------------------------------
0336:
0337:            // -----
0338:            // I18N String constants
0339:            private static final ResourceBundle messages = ResourceBundle
0340:                    .getBundle("org.netbeans.lib.profiler.Bundle"); // NOI18N
0341:            private static final String CANNOT_OPEN_SERVER_TEMPFILE_MSG = messages
0342:                    .getString("ProfilerClient_CannotOpenServerTempFileMsg"); // NOI18N
0343:            private static final String PERFORMING_INSTRUMENTATION_STRING = messages
0344:                    .getString("ProfilerClient_PerformingInstrumentationString"); // NOI18N
0345:            private static final String INVALID_CODE_REGION_MSG = messages
0346:                    .getString("ProfilerClient_InvalidCodeRegionMsg"); // NOI18N
0347:            private static final String CLASS_NOT_FOUND_MSG = messages
0348:                    .getString("ProfilerClient_ClassNotFoundMsg"); // NOI18N
0349:            private static final String OUT_OF_MEMORY_MSG = messages
0350:                    .getString("ProfilerClient_OutOfMemoryMsg"); // NOI18N
0351:            private static final String INCORRECT_AGENT_VERSION_MSG = messages
0352:                    .getString("ProfilerClient_IncorrectAgentVersionMsg"); // NOI18N
0353:            private static final String ERROR_GETTING_CALIBRATION_DATA_MSG = messages
0354:                    .getString("ProfilerClient_ErrorGettingCalibrationDataMsg"); // NOI18N
0355:            private static final String MUST_CALIBRATE_FIRST_MSG = messages
0356:                    .getString("ProfilerClient_MustCalibrateFirstMsg"); // NOI18N
0357:            private static final String MUST_CALIBRATE_FIRST_SHORT_MSG = messages
0358:                    .getString("ProfilerClient_MustCalibrateFirstShortMsg"); // NOI18N
0359:            private static final String INSTRUMENTATION_LIMIT_REACHED_MSG = messages
0360:                    .getString("ProfilerClient_InstrumentationLimitReachedMsg"); // NOI18N
0361:            private static final String CORRUPTED_TARGET_CALIBRATION_DATA_MSG = messages
0362:                    .getString("ProfilerClient_CorruptedTargetCalibrationDataMsg"); // NOI18N
0363:            private static final String CONNECT_VM_MSG = messages
0364:                    .getString("ProfilerClient_ConnectVmMsg"); // NOI18N
0365:            private static final String TARGET_JVM_ERROR_MSG = messages
0366:                    .getString("ProfilerClient_TargetJvmErrorMsg"); // NOI18N
0367:            private static final String UNSUPPORTED_JVM_MSG = messages
0368:                    .getString("ProfilerClient_UnsupportedJvmMsg"); // NOI18N
0369:            // -----
0370:            private static final String a = "AAQ";
0371:
0372:            //~ Instance fields ----------------------------------------------------------------------------------------------------------
0373:
0374:            private AppStatusHandler.ServerCommandHandler serverCommandHandler;
0375:            private AppStatusHandler appStatusHandler;
0376:            private CCTResultsFilter markFilter;
0377:            private CPUCCTProvider cpuCctProvider;
0378:            private Command execInSeparateThreadCmd;
0379:            private FlatProfileProvider flatProvider;
0380:            private InitiateInstrumentationCommand commandOnStartup = null;
0381:            private Instrumentor instrumentor;
0382:            private MemoryCCTProvider memCctProvider;
0383:            private Object execInSeparateThreadLock = new Object();
0384:            private Object forceObtainedResultsDumpLock = new Object(); // To make dump processing and other commands mutually
0385:            // exclusive
0386:
0387:            /*instrMethodGroupFromRootComplete, */
0388:            private Object instrumentationLock = new Object(); // To make sure all instrumentation-related operations
0389:            // happen serially
0390:            private Object responseLock = new Object();
0391:            private Object wdLock = new Object();
0392:            private ObjectInputStream socketIn;
0393:            private ObjectOutputStream socketOut;
0394:            private ProfilerEngineSettings settings;
0395:            private ProfilingSessionStatus status;
0396:            private Response lastResponse;
0397:            private SeparateCmdExecutionThread separateCmdExecThread;
0398:            private ServerListener serverListener;
0399:
0400:            //--------------------- Connection management --------------------
0401:            private Socket clientSocket;
0402:            private TimeCollector timeCollector;
0403:            private WireIO wireIO;
0404:
0405:            /**
0406:             * Needed to make memory profiling results available after app/VM shutdown
0407:             *
0408:             * Note that we don't have anything like getMemoryProfilingResult() here - essentially because we don't have memory
0409:             * results snapshots yet. Those, in turn, are not implemented because of performance concerns (reproducing our,
0410:             * potentially huge, hash table containing all tracked object, plus the call trees for these object allocations,
0411:             * every time that the user hits "Get results" seems scary). So instead of snapshots, we give the user various
0412:             * aspects of (constantly updated) memory profiling data on demand. Methods that return it are public ones in
0413:             * ObjAllocCallGraphBuilder, ObjLivenessCallGraphBuilder, and MemoryCallGraphBuilder.
0414:             * The getAllocatedObjectsCountResults() method below provides only one aspect of the memory profiling data.
0415:             */
0416:            private int[] savedAllocatedObjectsCountResults;
0417:            private volatile boolean connectionWithServerOpen; // Used just to prevent double entry into closeConnection()
0418:            private volatile boolean forceObtainedResultsDumpCalled;
0419:            private volatile boolean handlingEventBufferDump;
0420:            private volatile boolean instrMethodsLimitReported;
0421:            private boolean serverClassesInitialized;
0422:            private boolean shouldDisplayDialog = true;
0423:            private volatile boolean targetVMAlive;
0424:            private volatile boolean terminateOrDetachCommandIssued;
0425:            private int currentAgentId = -1;
0426:            private long instrProcessingTime;
0427:            private long resultsStart;
0428:
0429:            //~ Constructors -------------------------------------------------------------------------------------------------------------
0430:
0431:            public ProfilerClient(ProfilerEngineSettings settings,
0432:                    ProfilingSessionStatus status, AppStatusHandler ash,
0433:                    AppStatusHandler.ServerCommandHandler sch) {
0434:                this .settings = settings;
0435:                this .status = status;
0436:                appStatusHandler = ash;
0437:                serverCommandHandler = sch;
0438:                instrumentor = new Instrumentor(status, settings);
0439:
0440:                if (separateCmdExecThread == null) {
0441:                    separateCmdExecThread = new SeparateCmdExecutionThread();
0442:                    separateCmdExecThread.setDaemon(true);
0443:                    separateCmdExecThread.start();
0444:                }
0445:
0446:                EventBufferProcessor.initialize(this );
0447:                EventBufferResultsProvider.getDefault().addDispatcher(
0448:                        ProfilingResultsDispatcher.getDefault());
0449:            }
0450:
0451:            //~ Methods ------------------------------------------------------------------------------------------------------------------
0452:
0453:            /**
0454:             * Returns the array where element at index I is the total number of allocated objects for the class with I id.
0455:             * The relevant counters are kept at the server side and returned to the tool on demand, here.
0456:             */
0457:            public synchronized int[] getAllocatedObjectsCountResults()
0458:                    throws ClientUtils.TargetAppOrVMTerminated {
0459:                if (!targetVMAlive) {
0460:                    if (savedAllocatedObjectsCountResults != null) {
0461:                        return savedAllocatedObjectsCountResults;
0462:                    } else {
0463:                        throw new ClientUtils.TargetAppOrVMTerminated(
0464:                                ClientUtils.TargetAppOrVMTerminated.VM);
0465:                    }
0466:                }
0467:
0468:                savedAllocatedObjectsCountResults = null;
0469:                checkForTargetVMAlive();
0470:                sendSimpleCmdToServer(Command.GET_OBJECT_ALLOCATION_RESULTS);
0471:
0472:                ObjectAllocationResultsResponse resp = (ObjectAllocationResultsResponse) getAndCheckLastResponse("Unknown problem when trying to get allocated object count results." // NOI18N
0473:                ); // NOI18N
0474:
0475:                return resp.getResults();
0476:            }
0477:
0478:            /**
0479:             * Returns the snapshot of current multi-method CPU profiling results
0480:             *
0481:             * @return CPU Results snapshot
0482:             * @throws ClientUtils.TargetAppOrVMTerminated
0483:             *          In case the profiled application has already terminated
0484:             * @throws CPUResultsSnapshot.NoDataAvailableException
0485:             *          If no data are available yet
0486:             */
0487:            public synchronized CPUResultsSnapshot getCPUProfilingResultsSnapshot()
0488:                    throws ClientUtils.TargetAppOrVMTerminated,
0489:                    CPUResultsSnapshot.NoDataAvailableException {
0490:                return getCPUProfilingResultsSnapshot(true);
0491:            }
0492:
0493:            /**
0494:             * Returns the snapshot of current multi-method CPU profiling results
0495:             *
0496:             * @param dump true to fetch latest events from server, false otherwise (use only available data)
0497:             * @return CPU Results snapshot
0498:             * @throws ClientUtils.TargetAppOrVMTerminated
0499:             *          In case the profiled application has already terminated
0500:             * @throws CPUResultsSnapshot.NoDataAvailableException
0501:             *          If no data are available yet
0502:             */
0503:            public synchronized CPUResultsSnapshot getCPUProfilingResultsSnapshot(
0504:                    boolean dump) throws ClientUtils.TargetAppOrVMTerminated,
0505:                    CPUResultsSnapshot.NoDataAvailableException {
0506:                checkForTargetVMAlive();
0507:
0508:                if (dump) {
0509:                    if (!forceObtainedResultsDump(false, 5)) {
0510:                        return null;
0511:                    }
0512:                }
0513:
0514:                return new CPUResultsSnapshot(resultsStart, System
0515:                        .currentTimeMillis(), cpuCctProvider, status);
0516:            }
0517:
0518:            /**
0519:             * Returns the snapshot of current code region profiling results
0520:             */
0521:            public synchronized CodeRegionResultsSnapshot getCodeRegionProfilingResultsSnapshot()
0522:                    throws ClientUtils.TargetAppOrVMTerminated {
0523:                checkForTargetVMAlive();
0524:                sendSimpleCmdToServer(Command.GET_CODE_REGION_CPU_RESULTS);
0525:
0526:                CodeRegionCPUResultsResponse resp = (CodeRegionCPUResultsResponse) getAndCheckLastResponse("Unknown problem when trying to get code region CPU results." // NOI18N
0527:                ); // NOI18N
0528:
0529:                return new CodeRegionResultsSnapshot(resultsStart, System
0530:                        .currentTimeMillis(), resp.getResults(),
0531:                        status.timerCountsInSecond[0]);
0532:            }
0533:
0534:            public int getCurrentAgentId() {
0535:                return currentAgentId;
0536:            }
0537:
0538:            public void setCurrentInstrType(int type) {
0539:                status.currentInstrType = type;
0540:            }
0541:
0542:            public int getCurrentInstrType() {
0543:                return status.currentInstrType;
0544:            }
0545:
0546:            /**
0547:             * Determine which of the currently tracked threads are dead or alive. If the VM is not running, just returns null -
0548:             * it's clear that all threads are dead then.
0549:             */
0550:            public synchronized byte[] getCurrentThreadsLivenessStatus() {
0551:                try {
0552:                    checkForTargetVMAlive();
0553:                    sendSimpleCmdToServer(Command.GET_THREAD_LIVENESS_STATUS);
0554:
0555:                    ThreadLivenessStatusResponse resp = (ThreadLivenessStatusResponse) getAndCheckLastResponse("Unknown problem when trying to get thread liveness information." // NOI18N
0556:                    ); // NOI18N
0557:
0558:                    return resp.getStatus();
0559:                } catch (ClientUtils.TargetAppOrVMTerminated ex) {
0560:                    if (serverListener.isRunning()) { // The possibly problematic situation is not known yet
0561:                        MiscUtils
0562:                                .printErrorMessage("in getCurrentThreadLivenessStatus(), caught exception: "
0563:                                        + ex); // NOI18N
0564:                    }
0565:
0566:                    return null;
0567:                }
0568:            }
0569:
0570:            /**
0571:             * For the class with the given name and the initiating class loader (see Java Language/JVM Spec for definitions),
0572:             * find out and return the defining class loader. Both class loaders are internal class loader ids.
0573:             */
0574:            public synchronized int getDefiningClassLoaderId(String className,
0575:                    int initiatingLoaderId)
0576:                    throws ClientUtils.TargetAppOrVMTerminated {
0577:                checkForTargetVMAlive();
0578:
0579:                GetDefiningClassLoaderCommand cmd = new GetDefiningClassLoaderCommand(
0580:                        className, initiatingLoaderId);
0581:                sendComplexCmdToServer(cmd);
0582:
0583:                DefiningLoaderResponse resp = (DefiningLoaderResponse) getAndCheckLastResponse("Unknown problem when trying to get a defining loader for class" // NOI18N
0584:                ); // NOI18N
0585:
0586:                return resp.getLoaderId();
0587:            }
0588:
0589:            public FlatProfileProvider getFlatProfileProvider() {
0590:                return flatProvider;
0591:            }
0592:
0593:            public long getInstrProcessingTime() {
0594:                return instrProcessingTime;
0595:            }
0596:
0597:            //---------------- Internal statistics and other target VM information obtaining ----------------
0598:            public synchronized InternalStatsResponse getInternalStats()
0599:                    throws ClientUtils.TargetAppOrVMTerminated {
0600:                checkForTargetVMAlive();
0601:                sendSimpleCmdToServer(Command.GET_INTERNAL_STATS);
0602:
0603:                InternalStatsResponse resp = (InternalStatsResponse) getLastResponse();
0604:
0605:                return resp;
0606:            }
0607:
0608:            public CCTResultsFilter getMarkFilter() {
0609:                return markFilter;
0610:            }
0611:
0612:            public MemoryCCTProvider getMemoryCCTProvider() {
0613:                return memCctProvider;
0614:            }
0615:
0616:            /**
0617:             * Returns the snapshot of current Memory profiling results
0618:             *
0619:             * @return Memory Results snapshot
0620:             * @throws ClientUtils.TargetAppOrVMTerminated
0621:             *          In case the profiled application has already terminated
0622:             */
0623:            public synchronized MemoryResultsSnapshot getMemoryProfilingResultsSnapshot()
0624:                    throws ClientUtils.TargetAppOrVMTerminated {
0625:                return getMemoryProfilingResultsSnapshot(true);
0626:            }
0627:
0628:            /**
0629:             * Returns the snapshot of current Memory profiling results
0630:             *
0631:             * @param dump true to fetch latest events from server, false otherwise (use only available data)
0632:             * @return Memory Results snapshot
0633:             * @throws ClientUtils.TargetAppOrVMTerminated
0634:             *          In case the profiled application has already terminated
0635:             */
0636:            public synchronized MemoryResultsSnapshot getMemoryProfilingResultsSnapshot(
0637:                    boolean dump) throws ClientUtils.TargetAppOrVMTerminated {
0638:                checkForTargetVMAlive();
0639:
0640:                if (dump) {
0641:                    if (!forceObtainedResultsDump(false, 5)) {
0642:                        return null;
0643:                    }
0644:                }
0645:
0646:                memCctProvider.beginTrans(false);
0647:
0648:                try {
0649:                    memCctProvider.updateInternals();
0650:
0651:                    if (getCurrentInstrType() == INSTR_OBJECT_ALLOCATIONS) {
0652:                        return new AllocMemoryResultsSnapshot(resultsStart,
0653:                                System.currentTimeMillis(), memCctProvider,
0654:                                this );
0655:                    } else {
0656:                        return new LivenessMemoryResultsSnapshot(resultsStart,
0657:                                System.currentTimeMillis(), memCctProvider,
0658:                                this );
0659:                    }
0660:                } finally {
0661:                    memCctProvider.endTrans();
0662:                }
0663:            }
0664:
0665:            public Marker getMethodMarker() {
0666:                return settings.getMethodMarker();
0667:            }
0668:
0669:            /**
0670:             * Called to obtain method names for jMethodIds, that we do not know method names of.
0671:             * This method is typically called when results are to be displayed, but also in case some classes are unloaded
0672:             * in the profiled application, as in this case we would lost method names for already accumulated results.
0673:             * <p/>
0674:             * Assumption is that jMethodId is never reused inside the JVM.
0675:             *
0676:             * @param methodIds array of jMethodIds that we do not have names for
0677:             * @return the 3xn array, containing triplets of {class name, method name, method signature} strings for
0678:             *         given jmethodIds
0679:             */
0680:            public synchronized String[][] getMethodNamesForJMethodIds(
0681:                    int[] methodIds) throws ClientUtils.TargetAppOrVMTerminated {
0682:                checkForTargetVMAlive();
0683:
0684:                GetMethodNamesForJMethodIdsCommand cmd = new GetMethodNamesForJMethodIdsCommand(
0685:                        methodIds);
0686:                sendComplexCmdToServer(cmd);
0687:
0688:                MethodNamesResponse resp = (MethodNamesResponse) getAndCheckLastResponse("Unknown problem when trying to get method names for jmethodIds" // NOI18N
0689:                ); // NOI18N
0690:
0691:                return StringUtils.convertPackedStringsIntoStringArrays(resp
0692:                        .getPackedData(), resp.getPackedArrayOffsets(), 3);
0693:            }
0694:
0695:            public synchronized MonitoredData getMonitoredData() {
0696:                try {
0697:                    checkForTargetVMAlive();
0698:                    sendSimpleCmdToServer(Command.GET_MONITORED_NUMBERS);
0699:
0700:                    Response resp = getAndCheckLastResponse("Unknown problem when trying to get memory numbers."); // NOI18N
0701:
0702:                    try {
0703:                        MonitoredNumbersResponse mresp = (MonitoredNumbersResponse) resp;
0704:
0705:                        return MonitoredData.getMonitoredData(mresp);
0706:                    } catch (ClassCastException ex) {
0707:                        // FIXME: this diagnostics stuff should be ultimately removed once the root cause of the problem is understood
0708:                        MiscUtils
0709:                                .printErrorMessage("caught ClassCastException in getMonitoredNumbers. The real class of resp is " // NOI18N
0710:                                        + resp.getClass().getName()
0711:                                        + ", resp = " + resp // NOI18N
0712:                                );
0713:                        throw ex;
0714:                    }
0715:                } catch (ClientUtils.TargetAppOrVMTerminated ex) {
0716:                    if (serverListener.isRunning()) { // The possibly problematic situation is not known yet
0717:                        MiscUtils
0718:                                .printErrorMessage("in getMonitoredData(), caught exception: "
0719:                                        + ex); // NOI18N
0720:                    }
0721:
0722:                    return null;
0723:                }
0724:            }
0725:
0726:            /**
0727:             * @return ProfilerEngineSettings current profiler engine settings
0728:             */
0729:            public ProfilerEngineSettings getSettings() {
0730:                return settings;
0731:            }
0732:
0733:            /**
0734:             * We are using this essentially to let user know when the longest part of what happens after hitting e.g.
0735:             * "Instrument Object Allocation", is complete. Otherwise it might be difficult to figure out what's going on
0736:             */
0737:
0738:            //  public boolean isInstrMethodGroupFromRootComplete()       { return instrMethodGroupFromRootComplete; }
0739:            //  public CPUCallGraphBuilder getCPUCallGraphBuilder() { return ccgb; }
0740:            //  public MemoryCallGraphBuilder getMemoryCallGraphBuilder() { return mcgb; }
0741:            public ObjectInputStream getSocketInputStream() {
0742:                return socketIn;
0743:            }
0744:
0745:            public ProfilingSessionStatus getStatus() {
0746:                return status;
0747:            }
0748:
0749:            public TimeCollector getTimeCollector() {
0750:                return timeCollector;
0751:            }
0752:
0753:            public synchronized boolean cpuResultsExist()
0754:                    throws ClientUtils.TargetAppOrVMTerminated {
0755:                checkForTargetVMAlive();
0756:                sendSimpleCmdToServer(Command.CPU_RESULTS_EXIST);
0757:
0758:                Response resp = getAndCheckLastResponse("Unknown problem when trying to check for CPU profiling results." // NOI18N
0759:                ); // NOI18N
0760:
0761:                return resp.yes();
0762:            }
0763:
0764:            public boolean currentInstrTypeIsMemoryProfiling() {
0765:                return ((status.currentInstrType == INSTR_OBJECT_ALLOCATIONS) || (status.currentInstrType == INSTR_OBJECT_LIVENESS));
0766:            }
0767:
0768:            public boolean currentInstrTypeIsRecursiveCPUProfiling() {
0769:                return ((status.currentInstrType == INSTR_RECURSIVE_FULL) || (status.currentInstrType == INSTR_RECURSIVE_SAMPLED));
0770:            }
0771:
0772:            /**
0773:             * Removes instrumentation for classes with ids such that unprofiledClassStatusArray[id] == false.
0774:             * For these classes, no memory profiling data will be generated anymore.
0775:             */
0776:            public void deinstrumentMemoryProfiledClasses(
0777:                    boolean[] unprofiledClassStatusArray)
0778:                    throws InstrumentationException,
0779:                    ClientUtils.TargetAppOrVMTerminated {
0780:                synchronized (instrumentationLock) {
0781:                    if (getCurrentInstrType() == INSTR_NONE) {
0782:                        return;
0783:                    }
0784:
0785:                    Response resp = null;
0786:                    checkForTargetAppRunning();
0787:
0788:                    long curTime = System.currentTimeMillis();
0789:                    InstrumentMethodGroupCommand cmd = instrumentor
0790:                            .getCommandToUnprofileClasses(unprofiledClassStatusArray);
0791:
0792:                    if (!cmd.isEmpty()) {
0793:                        synchronized (this ) {
0794:                            // System.out.println("*** Profiler Engine: deinstrumentMemoryProfiledClasses() produced command:"); cmd.dump();
0795:                            sendComplexCmdToServer(cmd);
0796:                            instrProcessingTime += (System.currentTimeMillis() - curTime);
0797:                            resp = getLastResponse();
0798:                        }
0799:
0800:                        if (!resp.isOK()) {
0801:                            throw new InstrumentationException(resp
0802:                                    .getErrorMessage());
0803:                        }
0804:                    }
0805:                }
0806:            }
0807:
0808:            public synchronized void detachFromTargetJVM()
0809:                    throws ClientUtils.TargetAppOrVMTerminated {
0810:                checkForTargetVMAlive();
0811:                terminateOrDetachCommandIssued = true;
0812:                sendSimpleCmdToServer(Command.DETACH);
0813:
0814:                try {
0815:                    getLastResponse();
0816:                } finally {
0817:                    closeConnection();
0818:                    EventBufferProcessor.removeEventBufferFile(); // Try again, just in case closeConnection returned without calling it
0819:                }
0820:            }
0821:
0822:            /**
0823:             * This is called in all modes, direct invoke or attachment, to establish connection with the target VM
0824:             * @param attachMode 0 = no attach, 1 = direct attach, 2 = dynamic attach
0825:             */
0826:            public boolean establishConnectionWithServer(int attachMode,
0827:                    boolean calibrationOnlyRun) {
0828:                // Make sure we initialize this field early - it may be changed once we connect to the JVM and find out its
0829:                // real version.
0830:                status.targetJDKVersionString = settings
0831:                        .getTargetJDKVersionString();
0832:
0833:                return connectToServer(attachMode, calibrationOnlyRun);
0834:            }
0835:
0836:            /**
0837:             * Tells the server to send the contents of its data buffer to the tool immediately, no matter whether it's
0838:             * full or not.
0839:             */
0840:            public boolean forceObtainedResultsDump()
0841:                    throws ClientUtils.TargetAppOrVMTerminated {
0842:                return forceObtainedResultsDump(false, 0);
0843:            }
0844:
0845:            public boolean forceObtainedResultsDump(boolean liveResults,
0846:                    int retries) throws ClientUtils.TargetAppOrVMTerminated {
0847:                boolean dumped = false;
0848:                int retryCounter = retries;
0849:
0850:                do {
0851:                    dumped = forceObtainedResultsDump(liveResults);
0852:
0853:                    if (!dumped) {
0854:                        try {
0855:                            Thread.sleep(200);
0856:                        } catch (InterruptedException e) {
0857:                            break;
0858:                        }
0859:                    }
0860:                } while (!dumped && (--retryCounter > 0));
0861:
0862:                return dumped;
0863:            }
0864:
0865:            /**
0866:             * Tells the server to send the contents of its data buffer to the tool immediately, no matter whether it's
0867:             * full or not.
0868:             */
0869:            public boolean forceObtainedResultsDump(boolean liveResults)
0870:                    throws ClientUtils.TargetAppOrVMTerminated {
0871:                // The locks below are in the special order, to prevent deadlocks
0872:                synchronized (this ) {
0873:                    synchronized (forceObtainedResultsDumpLock) {
0874:                        if (handlingEventBufferDump) {
0875:                            return true; // If dump handling is already in progress, don't force the second dump
0876:                        }
0877:
0878:                        // no reason (and may be dangerous) to send another force dump command
0879:                        checkForTargetVMAlive();
0880:                        forceObtainedResultsDumpCalled = true;
0881:                        sendSimpleCmdToServer(liveResults ? Command.DUMP_EXISTING_RESULTS_LIVE
0882:                                : Command.DUMP_EXISTING_RESULTS);
0883:
0884:                        DumpResultsResponse resp = (DumpResultsResponse) getLastResponse(); // NOI18N
0885:
0886:                        if (resp.yes()) {
0887:                            status.dumpAbsTimeStamp = resp
0888:                                    .getDumpAbsTimeStamp();
0889:                        } else {
0890:                            if (ProfilerLogger.isDebug()) {
0891:                                ProfilerLogger
0892:                                        .debug("Force Obtained Results - Received Dump Error "); // NOI18N
0893:                            }
0894:                        }
0895:
0896:                        forceObtainedResultsDumpCalled = false;
0897:
0898:                        return resp.yes();
0899:                    }
0900:                }
0901:            }
0902:
0903:            /**
0904:             * This should be called to initiate code region instrumentation for specified code region.
0905:             * The data is remembered or sent to the server immediately if TA is already running. The actual instrumentation
0906:             * starts when server informs the tool that the class to be instrumented is loaded.
0907:             */
0908:            public void initiateCodeRegionInstrumentation(
0909:                    ClientUtils.SourceCodeSelection[] s)
0910:                    throws ClassNotFoundException, BadLocationException,
0911:                    InstrumentationException, IOException, ClassFormatError,
0912:                    ClientUtils.TargetAppOrVMTerminated {
0913:                synchronized (instrumentationLock) {
0914:                    removeAllInstrumentation();
0915:
0916:                    if (status.targetAppRunning && status.remoteProfiling) {
0917:                        if (!getCalibrationData(true)) {
0918:                            return;
0919:                        }
0920:                    }
0921:
0922:                    instrumentor.setStatusInfoFromSourceCodeSelection(s);
0923:                    instrumentor.setSavedSourceCodeSelection(s);
0924:
0925:                    String className = instrumentor.getRootClassNames()[ProfilingSessionStatus.CODE_REGION_CLASS_IDX]
0926:                            .replace('/', '.'); // NOI18N
0927:                    InitiateInstrumentationCommand cmd = new InitiateInstrumentationCommand(
0928:                            INSTR_CODE_REGION, className, false,
0929:                            status.startProfilingPointsActive);
0930:                    commandOnStartup = cmd;
0931:
0932:                    setCurrentInstrType(INSTR_CODE_REGION);
0933:
0934:                    if (status.targetAppRunning) {
0935:                        sendSetInstrumentationParamsCmd(false);
0936:
0937:                        String errorMessage = sendCommandAndGetResponse(commandOnStartup);
0938:
0939:                        if (errorMessage != null) {
0940:                            appStatusHandler.displayWarning(errorMessage);
0941:                        }
0942:                    }
0943:                }
0944:            }
0945:
0946:            /**
0947:             * This should be called to initiate memory profiling instrumentation of specified type (object allocation or
0948:             * object liveness).
0949:             * The data is remembered or sent to the server immediately if TA is already running. The actual instrumentation
0950:             * starts when the TA is started and the first class of this app is loaded, or immediately if TA is already running.
0951:             */
0952:            public void initiateMemoryProfInstrumentation(int instrType)
0953:                    throws ClientUtils.TargetAppOrVMTerminated,
0954:                    InstrumentationException {
0955:                synchronized (instrumentationLock) {
0956:                    removeAllInstrumentation();
0957:
0958:                    // Set this root class name irrespective of whether the target app has been started or not.
0959:                    // If it's not yet started, then indeed instrumentation should be triggered by main class load event - otherwise
0960:                    // the first loaded class that we register in the server is some reflection class loaded in process of main()
0961:                    // invocation. It causes recursive invocations of classLoadHook() (because it also uses some reflection), thus
0962:                    // screwing up the instrumentation procedure.
0963:                    // If the target app is already running, then instrumentation starts immediately and isn't triggered by a class
0964:                    // load event. However, if the same cmd that we build here is then re-used as commandOnStartup, it should again
0965:                    // contain rootClassName.
0966:                    String rootClassName = settings.getMainClassName();
0967:                    InitiateInstrumentationCommand cmd = new InitiateInstrumentationCommand(
0968:                            instrType, rootClassName, false,
0969:                            status.startProfilingPointsActive);
0970:                    cmd
0971:                            .setProfilingPoints(settings
0972:                                    .getRuntimeProfilingPoints());
0973:                    commandOnStartup = cmd;
0974:
0975:                    //      switch (instrType) {
0976:                    //        case INSTR_OBJECT_ALLOCATIONS:
0977:                    //          mcgb = new ObjAllocCallGraphBuilder(this);
0978:                    //          break;
0979:                    //        case INSTR_OBJECT_LIVENESS:
0980:                    //          mcgb = new ObjLivenessCallGraphBuilder(this);
0981:                    //          break;
0982:                    //      }
0983:
0984:                    // See initiateRecursiveCPUProfInstrumentation for why it's important to setCurrentInstrType() early
0985:                    setCurrentInstrType(instrType);
0986:
0987:                    if (status.targetAppRunning) {
0988:                        sendSetInstrumentationParamsCmd(false);
0989:
0990:                        String errorMessage = sendCommandAndGetResponse(commandOnStartup);
0991:
0992:                        if (errorMessage != null) {
0993:                            appStatusHandler.displayWarning(errorMessage);
0994:                        }
0995:                    }
0996:
0997:                    //instrMethodGroupFromRootComplete = false;
0998:                }
0999:            }
1000:
1001:            /**
1002:             * This should be called to initiate CPU profiling instrumentation starting from specified root method(s).
1003:             * The data is remembered or sent to the server immediately if TA is already running. The actual instrumentation
1004:             * starts when server informs the tool that one of the classes to be instrumented is loaded.
1005:             */
1006:            public void initiateRecursiveCPUProfInstrumentation(
1007:                    ClientUtils.SourceCodeSelection[] s)
1008:                    throws ClassNotFoundException, BadLocationException,
1009:                    InstrumentationException, IOException, ClassFormatError,
1010:                    ClientUtils.TargetAppOrVMTerminated {
1011:                //    System.out.println("Initiating CPU instrumentation");
1012:                //    for(int i=0;i<s.length;i++) {
1013:                //      System.out.println(s[i]);
1014:                //    }
1015:                synchronized (instrumentationLock) {
1016:                    removeAllInstrumentation();
1017:
1018:                    if (status.targetAppRunning && status.remoteProfiling) {
1019:                        if (!getCalibrationData(true)) {
1020:                            return;
1021:                        }
1022:                    }
1023:
1024:                    instrumentor.setStatusInfoFromSourceCodeSelection(s);
1025:
1026:                    boolean instrSpawnedThreads = settings
1027:                            .getInstrumentSpawnedThreads();
1028:
1029:                    String[] rootClassNames = instrumentor.getRootClassNames();
1030:                    int instrType = (settings.getCPUProfilingType() == CPU_INSTR_FULL) ? INSTR_RECURSIVE_FULL
1031:                            : INSTR_RECURSIVE_SAMPLED;
1032:                    InitiateInstrumentationCommand cmd = new InitiateInstrumentationCommand(
1033:                            instrType, rootClassNames, instrSpawnedThreads,
1034:                            status.startProfilingPointsActive);
1035:                    cmd
1036:                            .setProfilingPoints(settings
1037:                                    .getRuntimeProfilingPoints());
1038:                    commandOnStartup = cmd;
1039:                    status.setTimerTypes(settings.getAbsoluteTimerOn(),
1040:                            settings.getThreadCPUTimerOn());
1041:
1042:                    // the following code is moved to the CPUCallGraphBuilder.startup() method
1043:                    //      switch (instrType) {
1044:                    //        case INSTR_RECURSIVE_FULL:
1045:                    //          ccgb = new FullInstrCPUCallGraphBuilder(this);
1046:                    //          break;
1047:                    //        case INSTR_RECURSIVE_SAMPLED:
1048:                    //          ccgb = new SampledInstrCPUCallGraphBuilder(this);
1049:                    //          break;
1050:                    //      }
1051:
1052:                    // It's important that we set current instr type *before* we make the following call. That's because,
1053:                    // if targetAppRunning, at the server side all the operations in reaction to the commandOnStartup are performed
1054:                    // in a separate thread. It appears that that thread may quickly send back the response with loaded classes etc..,
1055:                    // and that may happen *before* we get response below and set currentInstrType. This fixes that
1056:                    // (essentially, race condition) bug.
1057:                    setCurrentInstrType(instrType);
1058:
1059:                    if (status.targetAppRunning) {
1060:                        sendSetInstrumentationParamsCmd(false);
1061:
1062:                        String errorMessage = sendCommandAndGetResponse(commandOnStartup);
1063:
1064:                        if (errorMessage != null) {
1065:                            appStatusHandler.displayWarning(errorMessage);
1066:                        }
1067:                    }
1068:
1069:                    //      CPUResultsDispatcher.getInstance().setProfilerClient(this); // initialize CPUResultsDispatcher
1070:                    //instrMethodGroupFromRootComplete = false;
1071:                }
1072:            }
1073:
1074:            public synchronized boolean memoryResultsExist() {
1075:                return (getMemoryCCTProvider() != null)
1076:                        && (getMemoryCCTProvider().getStacksForClasses() != null);
1077:            }
1078:
1079:            /*
1080:             * A callback method to be executed at the beginning of profiling;
1081:             * will disappear once the snapshot generation routine is rewritten
1082:             */
1083:            public void registerCPUCCTProvider(CPUCCTProvider provider) {
1084:                cpuCctProvider = provider;
1085:            }
1086:
1087:            public void registerFlatProfileProvider(FlatProfileProvider provider) {
1088:                flatProvider = provider;
1089:            }
1090:
1091:            public void registerMarkFilter(CCTResultsFilter filter) {
1092:                markFilter = filter;
1093:            }
1094:
1095:            public void registerMemoryCCTProvider(MemoryCCTProvider provider) {
1096:                memCctProvider = provider;
1097:            }
1098:
1099:            public void registerTimeCollector(TimeCollector collector) {
1100:                timeCollector = collector;
1101:            }
1102:
1103:            public void removeAllInstrumentation(boolean cleanupClient)
1104:                    throws InstrumentationException {
1105:                synchronized (instrumentationLock) {
1106:                    if (getCurrentInstrType() == INSTR_NONE) {
1107:                        return;
1108:                    }
1109:
1110:                    commandOnStartup = null;
1111:
1112:                    if (cleanupClient) {
1113:                        status.resetInstrClassAndMethodInfo();
1114:                    }
1115:
1116:                    try {
1117:                        clearPreviousInstrumentationInServer();
1118:                    } catch (ClientUtils.TargetAppOrVMTerminated ex) { /* So be it */
1119:                    }
1120:
1121:                    setCurrentInstrType(INSTR_NONE);
1122:
1123:                    //instrMethodGroupFromRootComplete = true;  // False means we are awaiting this event or it's being processed
1124:                }
1125:            }
1126:
1127:            public void removeAllInstrumentation()
1128:                    throws InstrumentationException {
1129:                removeAllInstrumentation(true);
1130:            }
1131:
1132:            /**
1133:             * If the target VM is terminated, cleans up all localy cached data so that they can be
1134:             * GCd from the memory. If the TA is running, this method does nothing.
1135:             */
1136:            public void resetClientData() {
1137:                if (targetJVMIsAlive()) {
1138:                    return; // we should not do any of the following in this case
1139:                }
1140:
1141:                status.resetInstrClassAndMethodInfo();
1142:                instrumentor.resetPerVMInstanceData();
1143:
1144:                //    CPUResultsDispatcher.getInstance().stop();
1145:                //    mcgb = null;
1146:                //    CPUResultsDispatcher.getInstance().shutdown();
1147:            }
1148:
1149:            public synchronized void resetProfilerCollectors()
1150:                    throws ClientUtils.TargetAppOrVMTerminated {
1151:                checkForTargetVMAlive();
1152:                sendSimpleCmdToServer(Command.RESET_PROFILER_COLLECTORS);
1153:                getAndCheckLastResponse("Unknown problem when trying to reset profiler collectors."); // NOI18N
1154:            }
1155:
1156:            public synchronized void resumeTargetAppThreads()
1157:                    throws ClientUtils.TargetAppOrVMTerminated {
1158:                checkForTargetAppRunning();
1159:                sendSimpleCmdToServer(Command.RESUME_TARGET_APP);
1160:                getAndCheckLastResponse("Unknown problem when trying to resume app threads."); // NOI18N
1161:            }
1162:
1163:            public synchronized void runGC()
1164:                    throws ClientUtils.TargetAppOrVMTerminated {
1165:                checkForTargetVMAlive();
1166:                sendSimpleCmdToServer(Command.RUN_GC);
1167:                getAndCheckLastResponse("Unknown problem when trying to run GC"); // NOI18N
1168:            }
1169:
1170:            public void sendSetInstrumentationParamsCmd(boolean changeableOnly)
1171:                    throws ClientUtils.TargetAppOrVMTerminated {
1172:                SetChangeableInstrParamsCommand cmd = new SetChangeableInstrParamsCommand(
1173:                        settings.getNProfiledThreadsLimit(), settings
1174:                                .getSamplingInterval(), settings
1175:                                .getAllocTrackEvery(), settings
1176:                                .getAllocStackTraceLimit(), settings
1177:                                .getRunGCOnGetResultsInMemoryProfiling(),
1178:                        settings.getExcludeWaitTime(), settings
1179:                                .getExcludeWaitTime());
1180:
1181:                String errorMessage = sendCommandAndGetResponse(cmd);
1182:
1183:                if (errorMessage != null) {
1184:                    appStatusHandler.displayWarning(errorMessage);
1185:                }
1186:
1187:                if (!changeableOnly) {
1188:                    SetUnchangeableInstrParamsCommand cmd1 = new SetUnchangeableInstrParamsCommand(
1189:                            settings.getAbsoluteTimerOn(), settings
1190:                                    .getThreadCPUTimerOn(), settings
1191:                                    .getInstrScheme(), settings
1192:                                    .getCodeRegionCPUResBufSize());
1193:                    errorMessage = sendCommandAndGetResponse(cmd1);
1194:
1195:                    if (errorMessage != null) {
1196:                        appStatusHandler.displayWarning(errorMessage);
1197:                    }
1198:                }
1199:            }
1200:
1201:            /**
1202:             * This method is called both when the application is started by the tool, and when the tool attaches to a running
1203:             * application.
1204:             * It's called *after* the establishConnectionWithServer() above.
1205:             * sendExplicitStartCommand actually determines the mode - it's true if we really start the VM as opposed to
1206:             * attaching.
1207:             */
1208:            public boolean startTargetApp(boolean sendExplicitStartCommand)
1209:                    throws ClientUtils.TargetAppOrVMTerminated,
1210:                    ClientUtils.TargetAppFailedToStart {
1211:                status.resetInstrClassAndMethodInfo();
1212:                instrumentor.resetPerVMInstanceData();
1213:                status.setTimerTypes(settings.getAbsoluteTimerOn(), settings
1214:                        .getThreadCPUTimerOn());
1215:                serverCommandHandler.handleServerCommand(null); // To reset the displayed figures
1216:                checkForTargetVMAlive();
1217:                instrProcessingTime = 0;
1218:                instrMethodsLimitReported = false;
1219:
1220:                // Special treatment of the case when instrumentation type is changed between runs by simply
1221:                // switching a button in Settings
1222:                if (currentInstrTypeIsRecursiveCPUProfiling()) {
1223:                    setCurrentInstrType((settings.getCPUProfilingType() == CPU_INSTR_FULL) ? INSTR_RECURSIVE_FULL
1224:                            : INSTR_RECURSIVE_SAMPLED);
1225:
1226:                    if (commandOnStartup != null) {
1227:                        commandOnStartup.setInstrType(getCurrentInstrType());
1228:                    }
1229:                }
1230:
1231:                if (commandOnStartup != null) {
1232:                    // Always set the current instrumentation parameters first
1233:                    sendSetInstrumentationParamsCmd(false);
1234:
1235:                    switch (getCurrentInstrType()) {
1236:                    case INSTR_CODE_REGION:
1237:
1238:                        if (status.remoteProfiling && !getCalibrationData(true)) {
1239:                            try {
1240:                                terminateTargetJVM();
1241:                            } catch (ClientUtils.TargetAppOrVMTerminated e) {
1242:                            }
1243:
1244:                            return false;
1245:                        }
1246:
1247:                        break;
1248:                    case INSTR_RECURSIVE_FULL:
1249:                    case INSTR_RECURSIVE_SAMPLED:
1250:
1251:                        if (status.remoteProfiling && !getCalibrationData(true)) {
1252:                            try {
1253:                                terminateTargetJVM();
1254:                            } catch (ClientUtils.TargetAppOrVMTerminated e) {
1255:                            }
1256:
1257:                            return false;
1258:                        }
1259:
1260:                        if (settings.getInstrumentMethodInvoke()) {
1261:                            String error = sendSimpleCommandAndGetResponse(Command.INSTRUMENT_REFLECTION);
1262:
1263:                            if (error != null) {
1264:                                throw new ClientUtils.TargetAppFailedToStart(
1265:                                        error);
1266:                            }
1267:                        }
1268:
1269:                        // the following code is moved to the CPUCallGraphBuilder.startup() method
1270:                        //          if (getCurrentInstrType() == INSTR_RECURSIVE_FULL) {
1271:                        //            ccgb = new FullInstrCPUCallGraphBuilder(this);
1272:                        //          } else {
1273:                        //            ccgb = new SampledInstrCPUCallGraphBuilder(this);
1274:                        //          }
1275:                        //          CPUResultsDispatcher.getInstance().setProfilerClient(this);  // initialize CPUResultsDispatcher
1276:                        break;
1277:
1278:                    //        case INSTR_OBJECT_ALLOCATIONS:
1279:                    //          mcgb = new ObjAllocCallGraphBuilder(this);
1280:                    //          break;
1281:                    //        case INSTR_OBJECT_LIVENESS:
1282:                    //          mcgb = new ObjLivenessCallGraphBuilder(this);
1283:                    //          break;
1284:                    }
1285:
1286:                    String errorMessage = sendCommandAndGetResponse(commandOnStartup);
1287:
1288:                    if (errorMessage != null) {
1289:                        appStatusHandler
1290:                                .displayWarning("Profiler Agent Error: "
1291:                                        + errorMessage); // NOI18N
1292:                    }
1293:
1294:                    commandOnStartup = null;
1295:                } else {
1296:                    // Needed to e.g. prevent initiateInstrumentation() called later from attempting to
1297:                    // remove instrumentation from VM.
1298:                    setCurrentInstrType(INSTR_NONE);
1299:                }
1300:
1301:                if (sendExplicitStartCommand) {
1302:                    String error = sendSimpleCommandAndGetResponse(Command.START_TARGET_APP);
1303:
1304:                    if (error != null) {
1305:                        throw new ClientUtils.TargetAppFailedToStart(error);
1306:                    }
1307:                }
1308:
1309:                status.targetAppRunning = true;
1310:                checkForInstrMethodsLimitReached();
1311:                EventBufferResultsProvider.getDefault().startup(this );
1312:
1313:                return true;
1314:            }
1315:
1316:            //---------------- Target Application Thread Management ----------------
1317:            public synchronized void suspendTargetAppThreads()
1318:                    throws ClientUtils.TargetAppOrVMTerminated {
1319:                checkForTargetAppRunning();
1320:                sendSimpleCmdToServer(Command.SUSPEND_TARGET_APP);
1321:                getAndCheckLastResponse("Unknown problem when trying to suspend app threads."); // NOI18N
1322:            }
1323:
1324:            public synchronized boolean takeHeapDump(String outputFile)
1325:                    throws ClientUtils.TargetAppOrVMTerminated {
1326:                checkForTargetVMAlive();
1327:                sendComplexCmdToServer(new TakeHeapDumpCommand(outputFile));
1328:
1329:                Response resp = getAndCheckLastResponse("takeHeapDump."); // NOI18N
1330:
1331:                return resp.isOK();
1332:            }
1333:
1334:            public boolean targetAppIsRunning() {
1335:                return status.targetAppRunning;
1336:            }
1337:
1338:            public boolean targetJVMIsAlive() {
1339:                return targetVMAlive;
1340:            }
1341:
1342:            //---------------- Target Application/JVM Status Management ----------------
1343:            public synchronized void terminateTargetJVM()
1344:                    throws ClientUtils.TargetAppOrVMTerminated {
1345:                checkForTargetVMAlive();
1346:                terminateOrDetachCommandIssued = true;
1347:                sendSimpleCmdToServer(Command.TERMINATE_TARGET_JVM);
1348:
1349:                if (!getLastResponse().isOK()) {
1350:                    throw new ClientUtils.TargetAppOrVMTerminated(
1351:                            ClientUtils.TargetAppOrVMTerminated.VM,
1352:                            "Target JVM terminated or not responding" // NOI18N
1353:                    );
1354:                }
1355:
1356:                closeConnection();
1357:            }
1358:
1359:            private synchronized Response getAndCheckLastResponse(
1360:                    String errMessage)
1361:                    throws ClientUtils.TargetAppOrVMTerminated {
1362:                Response resp = getLastResponse();
1363:
1364:                if (!resp.isOK()) {
1365:                    MiscUtils
1366:                            .printErrorMessage("error in getAndCheckLastResponse: for "
1367:                                    + resp
1368:                                    + " got error message: " // NOI18N
1369:                                    + resp.getErrorMessage()
1370:                                    + " and context message " + errMessage // NOI18N
1371:                            ); // NOI18N
1372:                }
1373:
1374:                return resp;
1375:            }
1376:
1377:            private synchronized boolean getCalibrationData(
1378:                    boolean getStoredData)
1379:                    throws ClientUtils.TargetAppOrVMTerminated {
1380:                int cmdType = getStoredData ? Command.GET_STORED_CALIBRATION_DATA
1381:                        : Command.RUN_CALIBRATION_AND_GET_DATA;
1382:                sendSimpleCmdToServer(cmdType);
1383:
1384:                Response resp = getLastResponse();
1385:
1386:                if (!resp.isOK()) {
1387:                    String msg = resp.getErrorMessage();
1388:
1389:                    if (getStoredData) {
1390:                        msg = MessageFormat.format(
1391:                                CORRUPTED_TARGET_CALIBRATION_DATA_MSG,
1392:                                new Object[] { msg });
1393:                    }
1394:
1395:                    appStatusHandler.displayError(msg);
1396:
1397:                    return false;
1398:                }
1399:
1400:                CalibrationDataResponse cdr = (CalibrationDataResponse) resp;
1401:                status.methodEntryExitCallTime = cdr
1402:                        .getMethodEntryExitCallTime();
1403:                status.methodEntryExitInnerTime = cdr
1404:                        .getMethodEntryExitInnerTime();
1405:                status.methodEntryExitOuterTime = cdr
1406:                        .getMethodEntryExitOuterTime();
1407:                status.timerCountsInSecond = cdr.getTimerCountsInSecond();
1408:
1409:                return true;
1410:            }
1411:
1412:            private void setLastResponse(Response r) {
1413:                synchronized (responseLock) {
1414:                    lastResponse = r;
1415:
1416:                    try {
1417:                        responseLock.notify();
1418:                    } catch (IllegalMonitorStateException ex) {
1419:                        MiscUtils
1420:                                .internalError("ProfilerClient.setLastResponse()"); // NOI18N
1421:                    }
1422:                }
1423:            }
1424:
1425:            private synchronized Response getLastResponse()
1426:                    throws ClientUtils.TargetAppOrVMTerminated {
1427:                Response res;
1428:
1429:                checkForTargetVMAlive();
1430:                synchronized (responseLock) {
1431:                    while (lastResponse == null) {
1432:                        long start = System.currentTimeMillis();
1433:
1434:                        try {
1435:                            responseLock.wait(60000);
1436:                        } catch (InterruptedException ex) {
1437:                            MiscUtils
1438:                                    .internalError("InterruptedException in ProfilerClient.getLastResponse()"); // NOI18N
1439:                        }
1440:
1441:                        // If we have been waiting for above number of milliseconds and got no response, assume that we timed out
1442:                        // and target JVM is dead
1443:                        if (!targetVMAlive) {
1444:                            status.targetAppRunning = false;
1445:                            targetVMAlive = false;
1446:                            throw new ClientUtils.TargetAppOrVMTerminated(
1447:                                    ClientUtils.TargetAppOrVMTerminated.VM);
1448:                        } else if (lastResponse == null
1449:                                && wireIO.wasAlive() < start) { // timed out
1450:                            if (!appStatusHandler
1451:                                    .confirmWaitForConnectionReply()) {
1452:                                status.targetAppRunning = false;
1453:                                targetVMAlive = false;
1454:                                throw new ClientUtils.TargetAppOrVMTerminated(
1455:                                        ClientUtils.TargetAppOrVMTerminated.VM);
1456:                            }
1457:                        }
1458:                    }
1459:                    res = lastResponse;
1460:                    lastResponse = null;
1461:                }
1462:
1463:                return res;
1464:            }
1465:
1466:            /**
1467:             * Set at least some of the properties related to execution of the target JVM.
1468:             * If we attach to the target VM on-the-fly, we need to get everything from it.
1469:             * Otherwise, there are still some properties that we can guess in principle, but which we better ask the VM
1470:             * for, such as Java extension class path dirs and Java boot class path.
1471:             */
1472:            private boolean setVMProperties(VMPropertiesResponse resp,
1473:                    boolean terminateOnError) {
1474:                if (resp.getAgentVersion() != CommonConstants.CURRENT_AGENT_VERSION) {
1475:                    appStatusHandler
1476:                            .displayWarning(INCORRECT_AGENT_VERSION_MSG);
1477:                }
1478:
1479:                // Check if the VM version is supported by the Profiler
1480:                String jdkVersionString = resp.getJDKVersionString();
1481:
1482:                if (!MiscUtils.isSupportedRunningJVMVersion(jdkVersionString)) {
1483:                    String message = MessageFormat.format(UNSUPPORTED_JVM_MSG,
1484:                            new Object[] { jdkVersionString });
1485:                    appStatusHandler.displayErrorAndWaitForConfirm(message);
1486:
1487:                    try {
1488:                        if (terminateOnError) {
1489:                            terminateTargetJVM();
1490:                        } else {
1491:                            detachFromTargetJVM();
1492:                        }
1493:                    } catch (ClientUtils.TargetAppOrVMTerminated ex) {
1494:                    }
1495:
1496:                    return false;
1497:                }
1498:
1499:                // Check the VM version, and if it doesn't match the one set in the tool, check if we have saved calibration data
1500:                // for this VM version
1501:                String jdkVersionName = Platform
1502:                        .getJDKVersionString(jdkVersionString);
1503:                settings.setTargetJDKVersionString(jdkVersionName);
1504:                status.targetJDKVersionString = jdkVersionName;
1505:                status.fullTargetJDKVersionString = jdkVersionString;
1506:                currentAgentId = resp.getAgentId();
1507:
1508:                if (!status.remoteProfiling) {
1509:                    int res = CalibrationDataFileIO
1510:                            .readSavedCalibrationData(status);
1511:
1512:                    if (res < 0) { // Fatal error with reading saved file data - report the details
1513:
1514:                        String message = MessageFormat.format(
1515:                                ERROR_GETTING_CALIBRATION_DATA_MSG,
1516:                                new Object[] { CalibrationDataFileIO
1517:                                        .getErrorMessage() });
1518:                        appStatusHandler.displayErrorAndWaitForConfirm(message);
1519:
1520:                        return false;
1521:                    } else if (res > 0) { // Saved data file doesn't exist - notify the user and stop
1522:                        appStatusHandler
1523:                                .displayErrorWithDetailsAndWaitForConfirm(
1524:                                        MUST_CALIBRATE_FIRST_SHORT_MSG,
1525:                                        MUST_CALIBRATE_FIRST_MSG);
1526:
1527:                        try {
1528:                            if (terminateOnError) {
1529:                                terminateTargetJVM();
1530:                            } else {
1531:                                detachFromTargetJVM();
1532:                            }
1533:                        } catch (ClientUtils.TargetAppOrVMTerminated ex) {
1534:                        }
1535:
1536:                        return false;
1537:                    }
1538:                }
1539:
1540:                status.jvmArguments = resp.getJVMArguments();
1541:                status.javaCommand = resp.getJavaCommand();
1542:                status.targetMachineOSName = resp.getTargetMachineOSName();
1543:                status.maxHeapSize = resp.getMaxHeapSize();
1544:                status.startupTimeMillis = resp.getStartupTimeMillis();
1545:                status.startupTimeInCounts = resp.getStartupTimeInCounts();
1546:
1547:                if (!status.remoteProfiling) {
1548:                    settings.setWorkingDir(resp.getWorkingDir());
1549:                    settings.setVMClassPaths(resp.getJavaClassPath(), resp
1550:                            .getJavaExtDirs(), resp.getBootClassPath());
1551:                    ClassRepository.initClassPaths(settings.getWorkingDir(),
1552:                            settings.getVMClassPaths());
1553:                }
1554:
1555:                return true;
1556:            }
1557:
1558:            /**
1559:             * Check if we can't instrument more methods because the 64K limit is reachec
1560:             */
1561:            private void checkForInstrMethodsLimitReached() {
1562:                if ((status.getStartingMethodId() >= 65535)
1563:                        && !instrMethodsLimitReported
1564:                        && status.targetAppRunning) {
1565:                    appStatusHandler
1566:                            .displayWarningAndWaitForConfirm(INSTRUMENTATION_LIMIT_REACHED_MSG);
1567:                    instrMethodsLimitReported = true;
1568:                }
1569:            }
1570:
1571:            private void checkForTargetAppRunning()
1572:                    throws ClientUtils.TargetAppOrVMTerminated {
1573:                if (!status.targetAppRunning) {
1574:                    serverCommandHandler.handleServerCommand(null);
1575:                    throw new ClientUtils.TargetAppOrVMTerminated(
1576:                            ClientUtils.TargetAppOrVMTerminated.APP);
1577:                }
1578:            }
1579:
1580:            private void checkForTargetVMAlive()
1581:                    throws ClientUtils.TargetAppOrVMTerminated {
1582:                if (!targetVMAlive) {
1583:                    serverCommandHandler.handleServerCommand(null);
1584:                    throw new ClientUtils.TargetAppOrVMTerminated(
1585:                            ClientUtils.TargetAppOrVMTerminated.VM);
1586:                }
1587:            }
1588:
1589:            //-------------------------------- Private implementation ------------------------------------------
1590:            private void clearPreviousInstrumentationInServer()
1591:                    throws InstrumentationException,
1592:                    ClientUtils.TargetAppOrVMTerminated {
1593:                Response resp = null;
1594:                checkForTargetAppRunning();
1595:
1596:                // First send the command that will make the application stop emitting events
1597:                // But avoid doing that while we are processing the data at the client side, since it looks like when these two
1598:                // things happen at the same time, it's likely to cause problems.
1599:                // This is a quick fix. Probably a more solid solution is needed.
1600:                if (handlingEventBufferDump) {
1601:                    while (handlingEventBufferDump) {
1602:                        try {
1603:                            Thread.sleep(20);
1604:                        } catch (Exception ex) {
1605:                        }
1606:                    }
1607:                }
1608:
1609:                String error = sendSimpleCommandAndGetResponse(Command.DEACTIVATE_INJECTED_CODE);
1610:
1611:                if (error != null) {
1612:                    throw new InstrumentationException(error);
1613:                }
1614:
1615:                long curTime = System.currentTimeMillis();
1616:
1617:                // Now actually de-instrument the instrumented methods
1618:                InstrumentMethodGroupCommand cmd = instrumentor
1619:                        .createClearAllInstrumentationCommand();
1620:
1621:                synchronized (this ) {
1622:                    sendComplexCmdToServer(cmd);
1623:                    instrProcessingTime += (System.currentTimeMillis() - curTime);
1624:                    resp = getLastResponse();
1625:                }
1626:
1627:                if (!resp.isOK()) {
1628:                    throw new InstrumentationException(resp.getErrorMessage());
1629:                }
1630:            }
1631:
1632:            private void closeConnection() {
1633:                if (!serverListener.isRunning()) {
1634:                    return;
1635:                }
1636:
1637:                try {
1638:                    status.targetAppRunning = false;
1639:                    targetVMAlive = false;
1640:                    serverListener.shutdown();
1641:                    setLastResponse(null); // This is important, in case smb. is waiting for the response
1642:                    socketOut.close();
1643:                    socketIn.close();
1644:                    clientSocket.close();
1645:
1646:                    // This is kind of "black magic", that is needed when we hit "Run" without explicitly terminating
1647:                    // the previous target JVM. If this pause is not made here, then for some reason we get:
1648:                    // "SocketException: Connection reset by peer: JVM_recv in socket input stream read"  in connectToServer().
1649:                    // I don't like this way of dealing with this problem - need to investigate why it really happens
1650:                    try {
1651:                        Thread.sleep(400);
1652:                    } catch (InterruptedException e) {
1653:                    }
1654:
1655:                    //serverCommandHandler.handleServerCommand(null); // does not seem to do anything
1656:                } catch (IOException ex) {
1657:                    // Don't do anything
1658:                } finally {
1659:                    EventBufferResultsProvider.getDefault().shutdown();
1660:                    EventBufferProcessor.removeEventBufferFile();
1661:                }
1662:            }
1663:
1664:            private boolean connectToServer(int attachMode,
1665:                    boolean calibrationOnlyRun) {
1666:                AppStatusHandler.AsyncDialog waitDialog;
1667:                status.targetAppRunning = false;
1668:                targetVMAlive = false;
1669:                terminateOrDetachCommandIssued = false;
1670:
1671:                String taHost = (attachMode == 1) ? settings.getRemoteHost()
1672:                        : ""; // NOI18N
1673:
1674:                if (taHost.equals("") || taHost.equals("localhost")
1675:                        || taHost.equals("127.0.0.1")) { // NOI18N
1676:                    status.remoteProfiling = false;
1677:                    taHost = "127.0.0.1"; // NOI18N
1678:                } else {
1679:                    status.remoteProfiling = true;
1680:                }
1681:
1682:                final String host = taHost;
1683:                final int port = settings.getPortNo();
1684:                waitDialog = appStatusHandler.getAsyncDialogInstance(
1685:                        CONNECT_VM_MSG, true, true);
1686:                waitDialog.display();
1687:
1688:                boolean waitForDisplayAndCloseIt = true;
1689:                boolean waitForConnection = true;
1690:                int noOfCycles = 600; // Timeout is set to 150 sec
1691:
1692:                try {
1693:                    serverListener = new ServerListener();
1694:                    serverListener.start();
1695:
1696:                    while (waitForConnection) {
1697:                        try {
1698:                            clientSocket = new Socket(host, port);
1699:                            clientSocket.setSoTimeout(0); // ATTENTION: timeout may be found useful eventually...
1700:                            clientSocket.setTcpNoDelay(true); // Necessary at least on Solaris to avoid delays in e.g. readInt() etc.
1701:                            socketOut = new ObjectOutputStream(clientSocket
1702:                                    .getOutputStream());
1703:                            socketIn = new ObjectInputStream(clientSocket
1704:                                    .getInputStream());
1705:                            wireIO = new WireIO(socketOut, socketIn);
1706:
1707:                            waitForConnection = false;
1708:                            targetVMAlive = true; // This is in fact an assumption
1709:                            serverListener.startRunning();
1710:                        } catch (ConnectException ex) {
1711:                            // ex.printStackTrace (System.err);
1712:                            try {
1713:                                Thread.sleep(250);
1714:                            } catch (InterruptedException iex) {
1715:                            }
1716:
1717:                            if (waitDialog.cancelPressed()) {
1718:                                waitForConnection = false;
1719:                                serverListener.cancel();
1720:                            }
1721:
1722:                            if (--noOfCycles == 0) {
1723:                                MiscUtils
1724:                                        .printWarningMessage("timed out while trying to connect to the target JVM."); // NOI18N
1725:                                waitForConnection = false;
1726:                                serverListener.cancel();
1727:                            }
1728:                        }
1729:                    }
1730:                } catch (Exception ex) { // SocketException, UnknownHostException, IOException
1731:                    MiscUtils
1732:                            .printErrorMessage("exception while trying to connect to the target JVM:\n"
1733:                                    + ex); // NOI18N
1734:                } finally {
1735:                    waitDialog.close();
1736:                }
1737:
1738:                if (!serverListener.isRunning()) {
1739:                    MiscUtils
1740:                            .printErrorMessage("connection with server not open"); // NOI18N
1741:
1742:                    return false;
1743:                }
1744:
1745:                // Now check the connection and do other preparation work
1746:                try {
1747:                    String error = sendSimpleCommandAndGetResponse(Command.CHECK_CONNECTION);
1748:
1749:                    if (error != null) {
1750:                        targetVMAlive = false;
1751:                        MiscUtils
1752:                                .printErrorMessage("got error message from agent:"
1753:                                        + error); // NOI18N
1754:
1755:                        return false;
1756:                    }
1757:
1758:                    if (calibrationOnlyRun) {
1759:                        //        System.err.println("G1");
1760:                        boolean res = getCalibrationData(false);
1761:
1762:                        //        System.err.println("G2: "+res);
1763:                        try {
1764:                            terminateTargetJVM();
1765:                        } catch (ClientUtils.TargetAppOrVMTerminated e) {
1766:                            ProfilerLogger
1767:                                    .warning("terminateTargetJVM failed with TargetAppOrVMTerminated exception:"); // NOI18N
1768:                            ProfilerLogger.log(e);
1769:
1770:                            // this is OK here
1771:                        }
1772:
1773:                        //        System.err.println("G3");
1774:                        return res;
1775:                    }
1776:
1777:                    boolean terminateOnError = attachMode == 1; // in case of direct attach we don't want to have a JVM process hanging around waiting for the client to connect
1778:                    // Get VM properties
1779:
1780:                    synchronized (this ) {
1781:                        sendSimpleCmdToServer(Command.GET_VM_PROPERTIES);
1782:
1783:                        Response aResponse = getLastResponse();
1784:
1785:                        if (!(aResponse instanceof  VMPropertiesResponse)) {
1786:                            System.err.println("SEVERE: Received "
1787:                                    + aResponse.getClass().getName() + "("
1788:                                    + aResponse.toString()
1789:                                    + ") instead of VMPropertiesResponse");
1790:                        }
1791:
1792:                        if (!setVMProperties((VMPropertiesResponse) aResponse,
1793:                                terminateOnError)) {
1794:                            return false;
1795:                        }
1796:                    }
1797:
1798:                    // Send a command to initiate the fake RootClassLoadedCommand cycle, that forces initialization of some internal
1799:                    // server classes
1800:                    serverClassesInitialized = false;
1801:                    // Note that here we can't use normal getCmd(), since this shared object could already have been initialized with
1802:                    // real data.
1803:                    error = sendCommandAndGetResponse(new InitiateInstrumentationCommand(
1804:                            INSTR_RECURSIVE_FULL,
1805:                            "*FAKE_CLASS_FOR_INTERNAL_TEST*", false) // NOI18N
1806:                    ); // NOI18N
1807:
1808:                    if (error != null) {
1809:                        MiscUtils
1810:                                .printErrorMessage("got error message from agent:"
1811:                                        + error); // NOI18N
1812:                        targetVMAlive = false;
1813:
1814:                        return false;
1815:                    }
1816:
1817:                    noOfCycles = 20;
1818:
1819:                    while (!serverClassesInitialized && (--noOfCycles > 0)) {
1820:                        try {
1821:                            Thread.sleep(100);
1822:                        } catch (InterruptedException ex) {
1823:                        }
1824:                    }
1825:
1826:                    if (!serverClassesInitialized) {
1827:                        MiscUtils
1828:                                .printErrorMessage("timed out while trying to initialize internals in the target JVM."); // NOI18N
1829:                        targetVMAlive = false;
1830:
1831:                        return false;
1832:                    }
1833:
1834:                    try {
1835:                        Thread.sleep(100); // To make sure everything has finished on the server side.
1836:                    } catch (InterruptedException ex) {
1837:                    }
1838:                } catch (ClientUtils.TargetAppOrVMTerminated ex) {
1839:                    targetVMAlive = false;
1840:                    MiscUtils.printErrorMessage("target app terminated:"
1841:                            + ex.getMessage()); // NOI18N
1842:
1843:                    return false;
1844:                }
1845:
1846:                return true;
1847:            }
1848:
1849:            /**
1850:             * Some commands, e.g. those related to instrumentation, are executed in a separate thread, since they may in turn
1851:             * send requests and await response from the server. Thus the listener thread, that calls this method, should be made
1852:             * available quickly so that it can listen for the server again.
1853:             */
1854:            private void executeInSeparateThread(Command cmd) {
1855:                synchronized (execInSeparateThreadLock) {
1856:                    execInSeparateThreadCmd = cmd;
1857:
1858:                    try {
1859:                        execInSeparateThreadLock.notify();
1860:                    } catch (IllegalMonitorStateException ex) {
1861:                        MiscUtils
1862:                                .internalError("ProfilerClient.executeInSeparateThread()"); // NOI18N
1863:                    }
1864:                }
1865:            }
1866:
1867:            private boolean handleFakeClassLoad(RootClassLoadedCommand cmd) {
1868:                if (cmd.getAllLoadedClassNames()[0].equals("*FAKE_CLASS_1*")) { // NOI18N
1869:                    sendComplexRespToServer(new InstrumentMethodGroupResponse(
1870:                            new String[] { "*FAKE_CLASS_1*", "*FAKE_CLASS_2*" },
1871:                            new int[] { 0, 0 }, new byte[][] { { 0 }, { 0 } },
1872:                            null, 0));
1873:                    serverClassesInitialized = true;
1874:
1875:                    return true;
1876:                } else {
1877:                    return false;
1878:                }
1879:            }
1880:
1881:            private void handleIOExceptionOnSend(IOException ex)
1882:                    throws ClientUtils.TargetAppOrVMTerminated {
1883:                checkForTargetVMAlive();
1884:                // For now, assume that the server went away. TODO [misha] - can it happen for any other reason?
1885:                appStatusHandler
1886:                        .displayError(MessageFormat.format(
1887:                                TARGET_JVM_ERROR_MSG, new Object[] { ex
1888:                                        .getMessage() }));
1889:                closeConnection();
1890:                throw new ClientUtils.TargetAppOrVMTerminated(
1891:                        ClientUtils.TargetAppOrVMTerminated.VM);
1892:            }
1893:
1894:            private void instrumentMethodGroupFollowUp(Command cmd) {
1895:                synchronized (instrumentationLock) {
1896:                    long curTime = System.currentTimeMillis();
1897:                    InstrumentMethodGroupResponse imgr = instrumentor
1898:                            .createFollowUpInstrumentMethodGroupResponse(cmd);
1899:                    instrProcessingTime += (System.currentTimeMillis() - curTime);
1900:                    //if (imgr != null && ! imgr.isEmpty()) {
1901:                    // System.err.println("*** Profiler Engine: instrumentMethodGroupFollowUp() produced response:");
1902:                    // imgr.dump();
1903:                    // }
1904:                    sendComplexRespToServer(imgr);
1905:                }
1906:
1907:                checkForInstrMethodsLimitReached();
1908:            }
1909:
1910:            private void instrumentMethodGroupFromRoot(
1911:                    final RootClassLoadedCommand cmd) {
1912:                AppStatusHandler.AsyncDialog waitDialog = null;
1913:
1914:                synchronized (instrumentationLock) {
1915:                    try {
1916:                        InstrumentMethodGroupResponse imgr = null;
1917:
1918:                        if (!serverClassesInitialized) { // Check if it is a fake command from server, used to just pre-initialize
1919:                            // some internal server classes
1920:
1921:                            if (handleFakeClassLoad(cmd)) {
1922:                                return;
1923:                            }
1924:                        }
1925:
1926:                        if (currentInstrTypeIsRecursiveCPUProfiling()
1927:                                || currentInstrTypeIsMemoryProfiling()) {
1928:                            if (!EventBufferProcessor.bufFileExists()) {
1929:                                if (!EventBufferProcessor
1930:                                        .setEventBufferFile(cmd
1931:                                                .getEventBufferFileName())) {
1932:                                    appStatusHandler
1933:                                            .displayError(MessageFormat
1934:                                                    .format(
1935:                                                            CANNOT_OPEN_SERVER_TEMPFILE_MSG,
1936:                                                            new Object[] { cmd
1937:                                                                    .getEventBufferFileName() }));
1938:                                    sendComplexRespToServer(new InstrumentMethodGroupResponse(
1939:                                            null));
1940:
1941:                                    return;
1942:                                }
1943:                            }
1944:
1945:                            JMethodIdTable.reset();
1946:                        }
1947:
1948:                        appStatusHandler.pauseLiveUpdates();
1949:
1950:                        if (status.targetAppRunning) {
1951:                            waitDialog = appStatusHandler
1952:                                    .getAsyncDialogInstance(
1953:                                            PERFORMING_INSTRUMENTATION_STRING,
1954:                                            true, false);
1955:                            waitDialog.display();
1956:
1957:                            //          if (waitDialog != null) {
1958:                            //            final AppStatusHandler.AsyncDialog dialog = waitDialog;
1959:                            //            if (EventQueue.isDispatchThread()) {
1960:                            //              dialog.display();
1961:                            //            } else {
1962:                            //              EventQueue.invokeLater(new Runnable() {
1963:                            //                public void run() {
1964:                            //                  dialog.display();
1965:                            //                }
1966:                            //              });
1967:                            //            }
1968:                            //          }
1969:                        }
1970:
1971:                        // If the application is not running yet, it means that instrumentation is performed on startup. In that case,
1972:                        // it typically takes very short time, so there is no real need to display this progress dialog. Additionally,
1973:                        // the AWT Event Queue thread may be blocked in the call to startTargetApp, in which case this whole thing will
1974:                        // hang (due to getAsyncDialogInstance NB implementation waiting on this thread's lock).
1975:                        try {
1976:                            long curTime = System.currentTimeMillis();
1977:                            imgr = instrumentor
1978:                                    .createInitialInstrumentMethodGroupResponse(cmd);
1979:                            instrProcessingTime += (System.currentTimeMillis() - curTime);
1980:                        } catch (BadLocationException ex) {
1981:                            imgr = new InstrumentMethodGroupResponse(null);
1982:                            // Can currently happen only for INSTR_CODE_REGION
1983:                            appStatusHandler
1984:                                    .displayError(INVALID_CODE_REGION_MSG);
1985:                        } catch (ClassNotFoundException ex) {
1986:                            imgr = new InstrumentMethodGroupResponse(null);
1987:
1988:                            if (getCurrentInstrType() == INSTR_CODE_REGION) {
1989:                                appStatusHandler
1990:                                        .displayError(MessageFormat
1991:                                                .format(CLASS_NOT_FOUND_MSG,
1992:                                                        new Object[] { ex
1993:                                                                .getMessage() }));
1994:                            } else {
1995:                                MiscUtils
1996:                                        .printErrorMessage("problem in instrumentMethodGroupFromRoot: "
1997:                                                + ex); // NOI18N
1998:                            }
1999:                        } catch (Exception e) {
2000:                            MiscUtils
2001:                                    .printErrorMessage("in instrumentMethodGroupFromRoot(), caught exception: "
2002:                                            + e); // NOI18N
2003:                        }
2004:
2005:                        //if (imgr != null ! imgr.isEmpty()) {
2006:                        // System.err.println("*** Profiler Engine: instrumentMethodGroupFromRoot() produced response:");
2007:                        // imgr.dump(); }
2008:                        // else System.err.println("*** Profiler Engine: instrumentMethodGroupFromRoot() produced empty response");
2009:                        sendComplexRespToServer(imgr);
2010:                    } finally {
2011:                        if (waitDialog != null) {
2012:                            final AppStatusHandler.AsyncDialog dialog = waitDialog;
2013:
2014:                            if (EventQueue.isDispatchThread()) {
2015:                                dialog.close();
2016:                            } else {
2017:                                EventQueue.invokeLater(new Runnable() {
2018:                                    public void run() {
2019:                                        dialog.close();
2020:                                    }
2021:                                });
2022:                            }
2023:                        }
2024:
2025:                        appStatusHandler.resumeLiveUpdates();
2026:                    }
2027:                }
2028:            }
2029:
2030:            /**
2031:             * Upon receipt of the BUFFER_FULL command from the server, read and process the buffer contents
2032:             */
2033:            private void readAndProcessProfilingResults(
2034:                    EventBufferDumpedCommand cmd) {
2035:                int bufSize = cmd.getBufSize();
2036:
2037:                if (bufSize == 0) { // zero size may happen when dump is forced when there is actually no new information generated
2038:                    sendSimpleRespToServer(true, null);
2039:
2040:                    return;
2041:                }
2042:
2043:                handlingEventBufferDump = true;
2044:
2045:                int instrType = getCurrentInstrType();
2046:
2047:                // Results of memory profiling can be processed concurrently to take advantage of a possible multiprocessor machine.
2048:                // Similarly, during remote profiling any results can be processed concurrently, since processing on a different
2049:                // machine will not disturb execution timing on the TA machine. But for local CPU profiling we better not disturb
2050:                // execution further by introducing yet another concurrent CPU-bound thread. Note also that if this command is
2051:                // received as a result of the forced dump (as opposed to the normal one due to buffer overflow), the data should
2052:                // be processed synchronously to avoid e.g. a "no results" report when there are already some.
2053:
2054:                // update [ian] In case of remote profiling we actually can not process the results in concurrently,
2055:                // since there would suddenly be 2 pieces of code that simultaneously read from the socket stream
2056:                // leading to issue 59660: JFluid: error writing collected data to the socket
2057:                // see http://www.netbeans.org/issues/show_bug.cgi?id=59660 for details
2058:                if (currentInstrTypeIsMemoryProfiling()
2059:                        && !status.remoteProfiling
2060:                        && !forceObtainedResultsDumpCalled) {
2061:                    // Note that the call below may block, waiting for separarateCmdExecThread to finish its current job.
2062:                    // That means that nothing in readResultsFromBuffer() that this command eventually calls, is allowed to
2063:                    // send a command to the server and await a response. If that happens, the communication thread will be
2064:                    // unavailable for reading server's response (because it's waiting here), effectively causing a deadlock.
2065:                    executeInSeparateThread(cmd);
2066:                    handlingEventBufferDump = false;
2067:                } else {
2068:                    // Process profiling results synchronously in case of:
2069:                    //  - remote profiling
2070:                    //  - explicite Get results (forceObtainedResultsDumpCalled)
2071:                    //  - CPU or Code Fragment profiling
2072:                    EventBufferProcessor
2073:                            .readDataAndPrepareForProcessing(bufSize);
2074:                    EventBufferResultsProvider.getDefault().dataReady(bufSize,
2075:                            instrType);
2076:                    handlingEventBufferDump = false;
2077:                    sendSimpleRespToServer(true, null);
2078:                    forceObtainedResultsDumpCalled = false;
2079:                }
2080:            }
2081:
2082:            /**
2083:             * @param cmd Command to send
2084:             * @return null if command was confirmed OK from Agent, Error message otherwise
2085:             * @throws ClientUtils.TargetAppOrVMTerminated
2086:             *
2087:             */
2088:            private synchronized String sendCommandAndGetResponse(Command cmd)
2089:                    throws ClientUtils.TargetAppOrVMTerminated {
2090:                sendComplexCmdToServer(cmd);
2091:
2092:                Response resp = getLastResponse();
2093:
2094:                if (!resp.isOK()) {
2095:                    MiscUtils
2096:                            .printErrorMessage("error in sendCommandAndGetResponse: for cmd = "
2097:                                    + cmd // NOI18N
2098:                                    + " and resp = "
2099:                                    + resp
2100:                                    + " got error message: "
2101:                                    + resp.getErrorMessage() // NOI18N
2102:                            );
2103:
2104:                    return resp.getErrorMessage();
2105:                } else {
2106:                    return null;
2107:                }
2108:            }
2109:
2110:            private void sendComplexCmdToServer(Command cmd)
2111:                    throws ClientUtils.TargetAppOrVMTerminated {
2112:                try {
2113:                    wireIO.sendComplexCommand(cmd);
2114:                } catch (IOException ex) {
2115:                    handleIOExceptionOnSend(ex);
2116:                }
2117:            }
2118:
2119:            private void sendComplexRespToServer(Response resp) {
2120:                try {
2121:                    wireIO.sendComplexResponse(resp);
2122:                } catch (IOException ex) {
2123:                    MiscUtils
2124:                            .printErrorMessage("exception when trying to send a response: "
2125:                                    + ex); // NOI18N
2126:
2127:                    try {
2128:                        handleIOExceptionOnSend(ex);
2129:                    } catch (ClientUtils.TargetAppOrVMTerminated ex1) { /* All done already */
2130:                    }
2131:                }
2132:            }
2133:
2134:            private void sendSimpleCmdToServer(int cmdType)
2135:                    throws ClientUtils.TargetAppOrVMTerminated {
2136:                try {
2137:                    wireIO.sendSimpleCommand(cmdType);
2138:                } catch (IOException ex) {
2139:                    handleIOExceptionOnSend(ex);
2140:                }
2141:            }
2142:
2143:            /**
2144:             * @param cmd Command to send
2145:             * @return null if command was confirmed OK from Agent, Error message otherwise
2146:             * @throws ClientUtils.TargetAppOrVMTerminated
2147:             *
2148:             */
2149:            private synchronized String sendSimpleCommandAndGetResponse(
2150:                    int cmdType) throws ClientUtils.TargetAppOrVMTerminated {
2151:                sendSimpleCmdToServer(cmdType);
2152:
2153:                Response resp = getLastResponse();
2154:
2155:                if (!resp.isOK()) {
2156:                    MiscUtils
2157:                            .printErrorMessage("error in sendCommandAndGetResponse: for cmdType = "
2158:                                    + cmdType // NOI18N
2159:                                    + " and resp = "
2160:                                    + resp
2161:                                    + " got error message: "
2162:                                    + resp.getErrorMessage() // NOI18N
2163:                            );
2164:
2165:                    return resp.getErrorMessage();
2166:                } else {
2167:                    return null;
2168:                }
2169:            }
2170:
2171:            private void sendSimpleRespToServer(boolean val, String errorMessage) {
2172:                try {
2173:                    wireIO.sendSimpleResponse(val, errorMessage);
2174:                } catch (IOException ex) {
2175:                    try {
2176:                        handleIOExceptionOnSend(ex);
2177:                    } catch (ClientUtils.TargetAppOrVMTerminated ex1) { /* All done already */
2178:                    }
2179:                }
2180:            }
2181:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.