void (@NotNull Map<@NotNull String, @NotNull HotSwapFile> modifiedClasses) { DebuggerManagerThreadImpl.assertIsManagerThread(); if (modifiedClasses.isEmpty()) { myProgress.addMessage(myDebuggerSession, MessageCategory.INFORMATION, JavaDebuggerBundle.message("status.hotswap.loaded.classes.up.to.date")); return; } final DebugProcessImpl debugProcess = myDebuggerSession.getProcess(); final VirtualMachineProxyImpl virtualMachineProxy = debugProcess.getVirtualMachineProxy(); final Project project = debugProcess.getProject(); final BreakpointManager breakpointManager = (DebuggerManagerEx.getInstanceEx(project)).getBreakpointManager(); breakpointManager.disableBreakpoints(debugProcess); StackCapturingLineBreakpoint.deleteAll(debugProcess); //virtualMachineProxy.suspend(); if (LOG.isDebugEnabled()) { LOG.debug("Threads before hotswap:\n", StreamEx.of(ThreadDumpAction.buildThreadStates(virtualMachineProxy)).map(ThreadState::getStackTrace).joining("\n")); } if (Registry.is("debugger.resume.yourkit.threads")) { virtualMachineProxy.allThreads().stream() .filter(ThreadReferenceProxyImpl::isResumeOnHotSwap) .filter(ThreadReferenceProxyImpl::isSuspended) .forEach(t -> IntStream.range(0, t.getSuspendCount()).forEach(i -> t.resume())); } try { RedefineProcessor redefineProcessor = new RedefineProcessor(virtualMachineProxy); int processedEntriesCount = 0; for (Map.Entry<@NotNull String, @NotNull HotSwapFile> entry : modifiedClasses.entrySet()) { // stop if the process is finished already if (debugProcess.isDetached() || debugProcess.isDetaching()) { break; } if (redefineProcessor.mayCancel() && myProgress.isCancelled()) { break; } processedEntriesCount++; String qualifiedName = entry.getKey(); myProgress.setText(qualifiedName); myProgress.setFraction(processedEntriesCount / (double)modifiedClasses.size()); try { redefineProcessor.processClass(qualifiedName, entry.getValue().file); } catch (IOException e) { reportProblem(qualifiedName, e); } } if (redefineProcessor.mayCancel() && myProgress.isCancelled()) { return; } redefineProcessor.processPending(); myProgress.setFraction(1); final int partiallyRedefinedClassesCount = redefineProcessor.getPartiallyRedefinedClassesCount(); if (partiallyRedefinedClassesCount == 0) { myProgress.addMessage( myDebuggerSession, MessageCategory.INFORMATION, JavaDebuggerBundle.message("status.classes.reloaded", redefineProcessor.getProcessedClassesCount()) ); } else { final String message = JavaDebuggerBundle.message( "status.classes.not.all.versions.reloaded", partiallyRedefinedClassesCount, redefineProcessor.getProcessedClassesCount() ); myProgress.addMessage(myDebuggerSession, MessageCategory.WARNING, message); } LOG.debug("classes reloaded"); } catch (Throwable e) { processException(e); } debugProcess.onHotSwapFinished(); breakpointManager.reloadBreakpoints(); final Semaphore waitSemaphore = new Semaphore(); waitSemaphore.down(); SwingUtilities.invokeLater(() -> { try { if (!project.isDisposed()) { debugProcess.getRequestsManager().clearWarnings(); if (LOG.isDebugEnabled()) { LOG.debug("requests updated"); LOG.debug("time stamp set"); } myDebuggerSession.refresh(false); XDebugSession session = myDebuggerSession.getXDebugSession(); if (session != null) { session.rebuildViews(); } } } catch (Throwable e) { LOG.error(e); } finally { waitSemaphore.up(); } }); waitSemaphore.waitFor(); if (!project.isDisposed()) { try { breakpointManager.enableBreakpoints(debugProcess); StackCapturingLineBreakpoint.createAll(debugProcess); } catch (Exception e) { processException(e); } } }