@Override public void addBreakpoint(Breakpoint breakpoint) throws DebuggerException { final String className = breakpoint.getLocation().getTarget(); final int lineNumber = breakpoint.getLocation().getLineNumber(); List<ReferenceType> classes = vm.classesByName(className); // it may mean that class doesn't loaded by a target JVM yet if (classes.isEmpty()) { deferBreakpoint(breakpoint); throw new DebuggerException("Class not loaded"); } ReferenceType clazz = classes.get(0); List<com.sun.jdi.Location> locations; try { locations = clazz.locationsOfLine(lineNumber); } catch (AbsentInformationException | ClassNotPreparedException e) { throw new DebuggerException(e.getMessage(), e); } if (locations.isEmpty()) { throw new DebuggerException("Line " + lineNumber + " not found in class " + className); } com.sun.jdi.Location location = locations.get(0); if (location.method() == null) { // Line is out of method. throw new DebuggerException("Invalid line " + lineNumber + " in class " + className); } // Ignore new breakpoint if already have breakpoint at the same location. EventRequestManager requestManager = getEventManager(); for (BreakpointRequest breakpointRequest : requestManager.breakpointRequests()) { if (location.equals(breakpointRequest.location())) { LOG.debug("Breakpoint at {} already set", location); return; } } try { EventRequest breakPointRequest = requestManager.createBreakpointRequest(location); breakPointRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); String expression = breakpoint.getCondition(); if (!(expression == null || expression.isEmpty())) { ExpressionParser parser = ExpressionParser.newInstance(expression); breakPointRequest.putProperty( "org.eclipse.che.ide.java.debug.condition.expression.parser", parser); } breakPointRequest.setEnabled(true); } catch (NativeMethodException | IllegalThreadStateException | InvalidRequestStateException e) { throw new DebuggerException(e.getMessage(), e); } debuggerCallback.onEvent(new BreakpointActivatedEventImpl(breakpoint)); LOG.debug("Add breakpoint: {}", location); }
@SuppressWarnings("all") public static void replace(Debugger debugger, File classFile, String className) { VirtualMachine vm = debugger.getVm(); if (vm == null) return; if (!vm.canRedefineClasses()) return; byte[] classBytes = loadClassFile(classFile); if (classBytes == null) return; List classes = vm.classesByName(className); if (classes == null || classes.size() == 0) return; for (int i = 0; i < classes.size(); i++) { ReferenceType refType = (ReferenceType) classes.get(i); HashMap map = new HashMap(); map.put(refType, classBytes); vm.redefineClasses(map); } }
// -------- Delegation ------- @Override public List<ReferenceType> classesByName(String s) { return virtualMachine.classesByName(s); }
/** * Perform the 'hotswap' command. * * @param session JSwat session on which to operate. * @param args Tokenized string of command arguments. * @param out Output to write messages to. */ public void perform(Session session, CommandArguments args, Log out) { if (!session.isActive()) { throw new CommandException(Bundle.getString("noActiveSession")); } if (!args.hasMoreTokens()) { throw new MissingArgumentsException(); } // Name of class is required; name of .class file is optional. String cname = args.nextToken(); String cfile = null; if (args.hasMoreTokens()) { cfile = args.nextToken(); } // Find the ReferenceType for this class. VirtualMachine vm = session.getConnection().getVM(); List classes = vm.classesByName(cname); if (classes.size() == 0) { throw new CommandException(Bundle.getString("hotswap.noSuchClass")); } ReferenceType clazz = (ReferenceType) classes.get(0); // Did the user give us a .class file? InputStream is = null; if (cfile == null) { // Try to find the .class file. PathManager pathman = (PathManager) session.getManager(PathManager.class); SourceSource src = pathman.mapClass(clazz); if (src == null) { throw new CommandException(Bundle.getString("hotswap.fileNotFound")); } is = src.getInputStream(); } else { // A filename was given, just open it. try { is = new FileInputStream(cfile); } catch (FileNotFoundException fnfe) { throw new CommandException(Bundle.getString("hotswap.fileNotFound")); } } // Do the actual hotswap operation. try { Classes.hotswap(clazz, is, vm); out.writeln(Bundle.getString("hotswap.success")); } catch (UnsupportedOperationException uoe) { if (!vm.canRedefineClasses()) { throw new CommandException(Bundle.getString("hotswap.noHotSwap")); } else if (!vm.canAddMethod()) { throw new CommandException(Bundle.getString("hotswap.noAddMethod")); } else if (!vm.canUnrestrictedlyRedefineClasses()) { throw new CommandException(Bundle.getString("hotswap.noUnrestricted")); } else { throw new CommandException(Bundle.getString("hotswap.unsupported")); } } catch (IOException ioe) { throw new CommandException(Bundle.getString("hotswap.errorReadingFile") + ' ' + ioe); } catch (NoClassDefFoundError ncdfe) { throw new CommandException(Bundle.getString("hotswap.wrongClass")); } catch (VerifyError ve) { throw new CommandException(Bundle.getString("hotswap.verifyError") + ' ' + ve); } catch (UnsupportedClassVersionError ucve) { throw new CommandException(Bundle.getString("hotswap.versionError") + ' ' + ucve); } catch (ClassFormatError cfe) { throw new CommandException(Bundle.getString("hotswap.formatError") + ' ' + cfe); } catch (ClassCircularityError cce) { throw new CommandException(Bundle.getString("hotswap.circularity") + ' ' + cce); } finally { if (is != null) { try { is.close(); } catch (IOException ioe) { } } } } // perform
public boolean run(String codeSnippetClassName) { ClassType codeSnippetClass; ObjectReference codeSnippet; Method method; List arguments; ObjectReference codeSnippetRunner; try { // Get the code snippet class List classes = jdiVM.classesByName(codeSnippetClassName); while (classes.size() == 0) { try { Thread.sleep(100); } catch (InterruptedException e) { } classes = jdiVM.classesByName(codeSnippetClassName); if (classes.size() == 0) { // workaround bug in Standard VM Iterator iterator = this.jdiVM.allClasses().iterator(); while (iterator.hasNext()) { ReferenceType type = (ReferenceType) iterator.next(); if (type.name().equals(codeSnippetClassName)) { classes = new ArrayList(1); classes.add(type); break; } } } } codeSnippetClass = (ClassType) classes.get(0); // Create a new code snippet Method constructor = (Method) codeSnippetClass.methodsByName("<init>").get(0); codeSnippet = codeSnippetClass.newInstance( jdiThread, constructor, new ArrayList(), ClassType.INVOKE_SINGLE_THREADED); // Install local variables and "this" into generated fields StackFrame stackFrame = getStackFrame(); try { Iterator variables = stackFrame.visibleVariables().iterator(); while (variables.hasNext()) { LocalVariable jdiVariable = (LocalVariable) variables.next(); Value value = stackFrame.getValue(jdiVariable); Field field = codeSnippetClass.fieldByName(new String(LOCAL_VAR_PREFIX) + jdiVariable.name()); codeSnippet.setValue(field, value); } } catch (AbsentInformationException e) { // No variables } Field delegateThis = codeSnippetClass.fieldByName(new String(DELEGATE_THIS)); ObjectReference thisObject; if (delegateThis != null && ((thisObject = stackFrame.thisObject()) != null)) { codeSnippet.setValue(delegateThis, thisObject); } // Get the code snippet runner ClassType codeSnippetRunnerClass = (ClassType) jdiVM.classesByName(CODE_SNIPPET_RUNNER_CLASS_NAME).get(0); Field theRunner = codeSnippetRunnerClass.fieldByName(THE_RUNNER_FIELD); codeSnippetRunner = (ObjectReference) codeSnippetRunnerClass.getValue(theRunner); // Get the method 'runCodeSnippet' and its arguments method = (Method) codeSnippetRunnerClass.methodsByName(RUN_CODE_SNIPPET_METHOD).get(0); arguments = new ArrayList(); arguments.add(codeSnippet); } catch (ClassNotLoadedException e) { e.printStackTrace(); return false; } catch (IncompatibleThreadStateException e) { e.printStackTrace(); return false; } catch (InvalidTypeException e) { e.printStackTrace(); return false; } catch (InvocationException e) { e.printStackTrace(); return false; } try { // Invoke runCodeSnippet(CodeSnippet) codeSnippetRunner.invokeMethod( jdiThread, method, arguments, ClassType.INVOKE_SINGLE_THREADED); // Retrieve values of local variables and put them back in the stack frame StackFrame stackFrame = getStackFrame(); try { Iterator variables = stackFrame.visibleVariables().iterator(); while (variables.hasNext()) { LocalVariable jdiVariable = (LocalVariable) variables.next(); Field field = codeSnippetClass.fieldByName(new String(LOCAL_VAR_PREFIX) + jdiVariable.name()); Value value = codeSnippet.getValue(field); stackFrame.setValue(jdiVariable, value); } } catch (AbsentInformationException e) { // No variables } } catch (ClassNotLoadedException e) { e.printStackTrace(); } catch (IncompatibleThreadStateException e) { e.printStackTrace(); } catch (InvalidTypeException e) { e.printStackTrace(); } catch (InvocationException e) { e.printStackTrace(); } return true; }