Parcourir la source

debugger draft

Ranides Atterwim il y a 5 ans
Parent
commit
146bc899ee

+ 9 - 0
assira.debugger/src/main/java/net/ranides/demo/debugger/DiClass.java

@@ -0,0 +1,9 @@
+package net.ranides.demo.debugger;
+
+import net.ranides.assira.reflection.IClass;
+
+public interface DiClass extends IClass<Object> {
+
+    DiLocation locate(int line);
+
+}

+ 8 - 0
assira.debugger/src/main/java/net/ranides/demo/debugger/DiClasses.java

@@ -0,0 +1,8 @@
+package net.ranides.demo.debugger;
+
+import net.ranides.assira.reflection.*;
+
+public interface DiClasses extends IElements<DiClass> {
+
+
+}

+ 33 - 0
assira.debugger/src/main/java/net/ranides/demo/debugger/DiConnection.java

@@ -0,0 +1,33 @@
+package net.ranides.demo.debugger;
+
+import com.sun.jdi.VirtualMachine;
+import net.ranides.demo.debugger.impl.CDiConnection;
+
+import java.util.List;
+
+public interface DiConnection extends AutoCloseable {
+
+    static DiConnection connect(String addr) {
+        return CDiConnection.connect(addr);
+    }
+
+    static DiConnection connect(String host, String port) {
+        return CDiConnection.connect(host, port);
+    }
+
+    @Override
+    void close();
+
+    VirtualMachine vm();
+
+    DiMirror mirror();
+
+    DiLocation locate(String type, int line);
+
+    DiLocation locate(String location);
+
+    DiClasses types(String name);
+
+    DiClasses types();
+
+}

+ 9 - 0
assira.debugger/src/main/java/net/ranides/demo/debugger/DiException.java

@@ -0,0 +1,9 @@
+package net.ranides.demo.debugger;
+
+public class DiException extends RuntimeException {
+
+    public DiException(Throwable cause) {
+        super(cause);
+    }
+
+}

+ 29 - 0
assira.debugger/src/main/java/net/ranides/demo/debugger/DiLocation.java

@@ -0,0 +1,29 @@
+package net.ranides.demo.debugger;
+
+import com.sun.jdi.Locatable;
+import com.sun.jdi.Location;
+import com.sun.jdi.request.BreakpointRequest;
+import net.ranides.demo.debugger.impl.CDiLocation;
+
+public interface DiLocation {
+
+    static DiLocation of(Locatable element) {
+        return new CDiLocation(element);
+    }
+
+    static DiLocation of(Location location) {
+        return new CDiLocation(location);
+    }
+
+    String name();
+
+    int line();
+
+    BreakpointRequest breakpoint();
+
+    boolean corresponds(Locatable other);
+
+    boolean corresponds(Location other);
+
+    boolean corresponds(DiLocation other);
+}

+ 11 - 0
assira.debugger/src/main/java/net/ranides/demo/debugger/DiMirror.java

@@ -0,0 +1,11 @@
+package net.ranides.demo.debugger;
+
+import com.sun.jdi.Value;
+
+public interface DiMirror {
+
+    Value asMirror(Object value);
+
+    Object asPrimitive(Value value);
+
+}

+ 178 - 0
assira.debugger/src/main/java/net/ranides/demo/debugger/impl/CDiClass.java

@@ -0,0 +1,178 @@
+package net.ranides.demo.debugger.impl;
+
+import com.sun.jdi.AbsentInformationException;
+import com.sun.jdi.ClassType;
+import com.sun.jdi.ReferenceType;
+import com.sun.jdi.TypeComponent;
+import net.ranides.assira.collection.query.CQuery;
+import net.ranides.assira.collection.query.CQueryBuilder;
+import net.ranides.assira.reflection.*;
+import net.ranides.assira.reflection.impl.*;
+import net.ranides.demo.debugger.DiClass;
+import net.ranides.demo.debugger.DiException;
+import net.ranides.demo.debugger.DiLocation;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Optional;
+
+public class CDiClass extends AClass<Object> implements DiClass {
+
+    private final ClassType type;
+
+    protected CDiClass(ClassType type) {
+        this.type = type;
+    }
+
+    @Override
+    public DiLocation locate(int line) {
+        try {
+            return new CDiLocation(type.locationsOfLine(line).get(0));
+        } catch (AbsentInformationException ex) {
+            throw new DiException(ex);
+        }
+    }
+
+    @Override
+    public List<IClass<?>> params() {
+//        String gs = type.genericSignature();
+        throw new UnsupportedOperationException("implement");
+    }
+
+    @Override
+    public IFields fields() {
+        AHints attr = FElements.newHints();
+        return FElements.newFields(attr, CQueryBuilder.fromQuery(attr, this::getRFields));
+    }
+
+    private CQuery<IField> getRFields(AHints hints) {
+        if(hints.hintDeclared()) {
+            return CQueryBuilder
+                .fromCollection(type.fields())
+                .map(f -> new CDiField(true, f));
+        } else if(hints.hintAny()) {
+            return CQueryBuilder
+                .fromCollection(type.allFields())
+                .map(f -> new CDiField(isdecl(f), f));
+        } else {
+            return CQueryBuilder
+                .fromCollection(type.visibleFields())
+                .map(f -> new CDiField(isdecl(f), f));
+        }
+    }
+
+    @Override
+    public IConstructors<Object> constructors() {
+//        type.methodsByName("<init>");
+//        AHints attr = FElements.newHints();
+//        return FElements.newConstructors(attr, CQueryBuilder.fromQuery(attr, this::getRConstructors));
+        throw new UnsupportedOperationException("implement");
+    }
+
+    @Override
+    public IMethods methods() {
+        AHints attr = FElements.newHints();
+        return FElements.newMethods(attr, CQueryBuilder.fromQuery(attr, this::getRMethods));
+    }
+
+    private CQuery<IMethod> getRMethods(AHints hints) {
+        if(hints.hintDeclared()) {
+            return CQueryBuilder
+                .fromCollection(type.methods())
+                .map(m -> new CdiMethod(true, m));
+        } else if(hints.hintAny()) {
+            return CQueryBuilder
+                .fromCollection(type.allMethods())
+                .map(m -> new CdiMethod(isdecl(m), m));
+        } else {
+            return CQueryBuilder
+                .fromCollection(type.visibleMethods())
+                .map(m -> new CdiMethod(isdecl(m), m));
+        }
+    }
+
+    private boolean isdecl(TypeComponent ref) {
+        return type.equals(ref.declaringType());
+    }
+
+    @Override
+    public IClass<?> parent() {
+        return null;
+    }
+
+    @Override
+    public IClasses parents() {
+        return null;
+    }
+
+    @Override
+    public IClasses interfaces() {
+        return null;
+    }
+
+    @Override
+    public IClass<?> outer() {
+        return null;
+    }
+
+    @Override
+    public IClasses inner() {
+        return null;
+    }
+
+    @Override
+    public Class<?> raw() {
+        return null;
+    }
+
+    @Override
+    public String shortname() {
+        return null;
+    }
+
+    @Override
+    public IClass<?> component() {
+        return null;
+    }
+
+    @Override
+    public Type reflective() {
+        return null;
+    }
+
+    @Override
+    public boolean isInstance(Object value) {
+        return false;
+    }
+
+    @Override
+    public Object cast(Object value) {
+        return null;
+    }
+
+    @Override
+    public IContext context() {
+        return IContext.DEFAULT;
+    }
+
+    @Override
+    public String name() {
+        return type.name();
+    }
+
+    @Override
+    public IAttributes attributes() {
+        return null;
+    }
+
+    @Override
+    public IAnnotations annotations() {
+        return null;
+    }
+
+    @Override
+    public <A extends Annotation> Optional<A> annotation(Class<A> type) {
+        return Optional.empty();
+    }
+}

+ 32 - 0
assira.debugger/src/main/java/net/ranides/demo/debugger/impl/CDiClasses.java

@@ -0,0 +1,32 @@
+package net.ranides.demo.debugger.impl;
+
+import net.ranides.demo.debugger.DiClass;
+import net.ranides.demo.debugger.DiClasses;
+
+import net.ranides.assira.collection.query.CQuery;
+import net.ranides.assira.reflection.*;
+import net.ranides.assira.reflection.impl.AElements;
+import net.ranides.assira.reflection.impl.AHints;
+
+import java.util.List;
+
+public class CDiClasses extends AElements<DiClass> implements DiClasses {
+
+    public CDiClasses(CQuery<DiClass> cquery) {
+        super(AHints.EMPTY, cquery);
+    }
+
+    public CDiClasses(IHints hints, CQuery<DiClass> cquery) {
+        super(hints, cquery);
+    }
+
+    @Override
+    public List<String> names() {
+        return null;
+    }
+
+    @Override
+    public IElements<? extends IElement> parent() {
+        return null;
+    }
+}

+ 117 - 0
assira.debugger/src/main/java/net/ranides/demo/debugger/impl/CDiConnection.java

@@ -0,0 +1,117 @@
+package net.ranides.demo.debugger.impl;
+
+import com.sun.jdi.Bootstrap;
+import com.sun.jdi.ClassType;
+import com.sun.jdi.VirtualMachine;
+import com.sun.jdi.connect.AttachingConnector;
+import com.sun.jdi.connect.Connector;
+import com.sun.jdi.connect.IllegalConnectorArgumentsException;
+import com.sun.jdi.request.BreakpointRequest;
+
+import net.ranides.assira.collection.query.CQuery;
+import net.ranides.assira.collection.query.CQueryBuilder;
+import net.ranides.assira.generic.ValueUtils;
+import net.ranides.assira.reflection.IClass;
+import net.ranides.assira.text.StringUtils;
+import net.ranides.demo.debugger.DiClass;
+import net.ranides.demo.debugger.DiClasses;
+import net.ranides.demo.debugger.DiConnection;
+import net.ranides.demo.debugger.DiException;
+import net.ranides.demo.debugger.DiLocation;
+import net.ranides.demo.debugger.DiMirror;
+import net.ranides.demo.debugger.util.SimpleDebugger;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CDiConnection implements DiConnection {
+
+    final VirtualMachine vm;
+
+    final CDiMirror mirror;
+
+    private CDiConnection(String host, String port) {
+        AttachingConnector connector = Bootstrap.virtualMachineManager()
+            .attachingConnectors()
+            .stream()
+            .filter(v -> v.name().equals("com.sun.jdi.SocketAttach"))
+            .findFirst()
+            .orElseThrow(() -> new UnsupportedOperationException("No SocketAttachingConnector found."));
+
+        Map<String, Connector.Argument> args = connector.defaultArguments();
+        args.get("hostname").setValue(host);
+        args.get("port").setValue(port);
+
+        try {
+            this.vm = connector.attach(args);
+            this.mirror = new CDiMirror(vm);
+        } catch (IOException | IllegalConnectorArgumentsException cause) {
+            throw new DiException(cause);
+        }
+    }
+
+    public static DiConnection connect(String addr) {
+        Matcher hit = Pattern.compile("([^:]+)?(?:([0-9]+))").matcher(addr);
+        if(!hit.matches()) {
+            throw new DiException(new IllegalArgumentException("Invalid address: " + addr));
+        }
+        String host = ValueUtils.or(hit.group(1), "localhost");
+        String port = hit.group(2);
+        return connect(host, port);
+    }
+
+    public static DiConnection connect(String host, String port) {
+        return new CDiConnection(host, port);
+    }
+
+    @Override
+    public DiLocation locate(String type, int line) {
+        return types(type).first().map(c -> c.locate(line)).orElseThrow(NoSuchElementException::new);
+    }
+
+    @Override
+    public DiLocation locate(String location) {
+        String[] parts = location.split("@",2);
+        return locate(parts[0], Integer.parseInt(parts[1]));
+    }
+
+    @Override
+    public DiClasses types(String name) {
+        CQuery<DiClass> query = CQueryBuilder
+            .fromCollection(vm.classesByName(name))
+            .filter(ClassType.class::isInstance)
+            .map(ClassType.class::cast)
+            .map(CDiClass::new);
+        return new CDiClasses(query);
+    }
+
+    @Override
+    public DiClasses types() {
+        CQuery<DiClass> query = CQueryBuilder
+            .fromCollection(vm.allClasses())
+            .filter(ClassType.class::isInstance)
+            .map(ClassType.class::cast)
+            .map(CDiClass::new);
+        return new CDiClasses(query);
+    }
+
+    @Override
+    public VirtualMachine vm() {
+        return vm;
+    }
+
+    @Override
+    public DiMirror mirror() {
+        return mirror;
+    }
+
+    @Override
+    public void close() {
+        vm.dispose();
+    }
+}

+ 90 - 0
assira.debugger/src/main/java/net/ranides/demo/debugger/impl/CDiField.java

@@ -0,0 +1,90 @@
+package net.ranides.demo.debugger.impl;
+
+import com.sun.jdi.Field;
+import net.ranides.assira.generic.Wrapper;
+import net.ranides.assira.reflection.*;
+import net.ranides.assira.reflection.impl.AField;
+
+import java.lang.annotation.Annotation;
+import java.lang.invoke.MethodHandle;
+import java.util.Optional;
+
+public class CDiField extends AField implements IField {
+
+    private final boolean isDeclared;
+    private final Field field;
+
+    protected CDiField(boolean isDeclared, Field field) {
+        super(IContext.DEFAULT);
+        this.isDeclared = isDeclared;
+        this.field = field;
+    }
+
+    @Override
+    public String name() {
+        return field.name();
+    }
+
+    @Override
+    public IAttributes attributes() {
+        return null;
+    }
+
+    @Override
+    public IAnnotations annotations() {
+        return null;
+    }
+
+    @Override
+    public IClass<?> type() {
+        // field.type();
+        return null;
+    }
+
+    @Override
+    public IClass<?> parent() {
+        // field.declaringType()
+        return null;
+    }
+
+    @Override
+    public Object get(Object that) {
+
+        return null;
+    }
+
+    @Override
+    public void set(Object that, Object value) {
+
+    }
+
+    @Override
+    public java.lang.reflect.Field reflective() {
+        return null;
+    }
+
+    @Override
+    public IField rewritable() {
+        return null;
+    }
+
+    @Override
+    public IField accessible() {
+        return null;
+    }
+
+    @Override
+    public MethodHandle getter() {
+        return null;
+    }
+
+    @Override
+    public MethodHandle setter() {
+        return null;
+    }
+
+    @Override
+    public int hashCode() {
+        return field.hashCode();
+    }
+}

+ 61 - 0
assira.debugger/src/main/java/net/ranides/demo/debugger/impl/CDiLocation.java

@@ -0,0 +1,61 @@
+package net.ranides.demo.debugger.impl;
+
+import com.sun.jdi.Locatable;
+import com.sun.jdi.Location;
+import com.sun.jdi.request.BreakpointRequest;
+import net.ranides.demo.debugger.DiLocation;
+
+import net.ranides.assira.generic.HashUtils;
+
+public class CDiLocation implements DiLocation {
+
+    private final Location location;
+
+    public CDiLocation(Locatable element) {
+        this(element.location());
+    }
+
+    public CDiLocation(Location location) {
+        this.location = location;
+    }
+
+    @Override
+    public String name() {
+        return location.declaringType().name();
+    }
+
+    @Override
+    public int line() {
+        return location.lineNumber();
+    }
+
+    @Override
+    public BreakpointRequest breakpoint() {
+        return location.virtualMachine().eventRequestManager().createBreakpointRequest(location);
+    }
+
+    @Override
+    public int hashCode() {
+        return HashUtils.hashPair(name(), line());
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        return (other == this) || (other instanceof DiLocation) && corresponds((DiLocation) other);
+    }
+
+    @Override
+    public boolean corresponds(Locatable other) {
+        return corresponds(other.location());
+    }
+
+    @Override
+    public boolean corresponds(Location other) {
+        return name().equals(other.declaringType().name()) && line() == other.lineNumber();
+    }
+
+    @Override
+    public boolean corresponds(DiLocation other) {
+        return name().equals(other.name()) && line() == other.line();
+    }
+}

+ 76 - 0
assira.debugger/src/main/java/net/ranides/demo/debugger/impl/CDiMirror.java

@@ -0,0 +1,76 @@
+package net.ranides.demo.debugger.impl;
+
+import com.sun.jdi.*;
+import net.ranides.demo.debugger.DiMirror;
+
+public class CDiMirror implements DiMirror {
+
+    protected final VirtualMachine vm;
+
+    protected CDiMirror(VirtualMachine vm) {
+        this.vm = vm;
+    }
+
+    public Value asMirror(Object value) {
+        if (value instanceof String) {
+            return vm.mirrorOf((String) value);
+        }
+        if (value instanceof Integer) {
+            return vm.mirrorOf((Integer) value);
+        }
+        if (value instanceof Short) {
+            return vm.mirrorOf((Short) value);
+        }
+        if (value instanceof Byte) {
+            return vm.mirrorOf((Byte) value);
+        }
+        if (value instanceof Long) {
+            return vm.mirrorOf((Long) value);
+        }
+        if (value instanceof Float) {
+            return vm.mirrorOf((Float) value);
+        }
+        if (value instanceof Double) {
+            return vm.mirrorOf((Double) value);
+        }
+        if (value instanceof Boolean) {
+            return vm.mirrorOf((Boolean) value);
+        }
+        if (value instanceof Character) {
+            return vm.mirrorOf((Character) value);
+        }
+        throw new IllegalArgumentException("Not supported value: " + value);
+    }
+
+    public Object asPrimitive(Value value) {
+        if (value instanceof StringReference) {
+            return ((StringReference) value).value();
+        }
+        if (value instanceof IntegerValue) {
+            return ((IntegerValue) value).value();
+        }
+        if (value instanceof ShortValue) {
+            return ((ShortValue) value).value();
+        }
+        if (value instanceof ByteValue) {
+            return ((ByteValue) value).value();
+        }
+        if (value instanceof LongValue) {
+            return ((LongValue) value).value();
+        }
+        if (value instanceof FloatValue) {
+            return ((FloatValue) value).value();
+        }
+        if (value instanceof DoubleValue) {
+            return ((DoubleValue) value).value();
+        }
+        if (value instanceof BooleanValue) {
+            return ((BooleanValue) value).value();
+        }
+        if (value instanceof CharValue) {
+            return ((CharValue) value).value();
+        }
+        throw new IllegalArgumentException("Not supported value: " + value);
+    }
+
+}

+ 96 - 0
assira.debugger/src/main/java/net/ranides/demo/debugger/impl/CdiMethod.java

@@ -0,0 +1,96 @@
+package net.ranides.demo.debugger.impl;
+
+import net.ranides.assira.reflection.*;
+import net.ranides.assira.reflection.impl.AMethod;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.reflect.Method;
+import java.util.List;
+
+public class CdiMethod extends AMethod {
+
+    private final boolean isDeclared;
+
+    private final com.sun.jdi.Method method;
+
+    public CdiMethod(boolean isDeclared, com.sun.jdi.Method method) {
+        super(IContext.DEFAULT);
+        this.isDeclared = isDeclared;
+        this.method = method;
+    }
+
+    @Override
+    public String name() {
+        return method.name();
+    }
+
+    @Override
+    public IAttributes attributes() {
+        return null;
+    }
+
+    @Override
+    public IAnnotations annotations() {
+        return null;
+    }
+
+    @Override
+    public List<IClass<?>> params() {
+        return null;
+    }
+
+    @Override
+    public IClass<?> returns() {
+        return null;
+    }
+
+    @Override
+    public IArguments arguments() {
+        return null;
+    }
+
+    @Override
+    public List<IClass<?>> exceptions() {
+        return null;
+    }
+
+    @Override
+    public IClass<?> parent() {
+        return null;
+    }
+
+    @Override
+    public Object invoke() {
+        return null;
+    }
+
+    @Override
+    public Object invoke(Object that) {
+        return null;
+    }
+
+    @Override
+    public Object invoke(Object that, Object... arguments) {
+        return null;
+    }
+
+    @Override
+    public Object call(Object... arguments) {
+        return null;
+    }
+
+    @Override
+    public MethodHandle handle() {
+        return null;
+    }
+
+    @Override
+    public IMethod accessible() {
+        return null;
+    }
+
+    @Override
+    public Method reflective() {
+        return null;
+    }
+}

+ 17 - 96
assira.debugger/src/main/java/net/ranides/demo/debugger/SimpleDebugger.java

@@ -1,8 +1,6 @@
-package net.ranides.demo.debugger;
+package net.ranides.demo.debugger.util;
 
 import com.sun.jdi.*;
-import com.sun.jdi.connect.AttachingConnector;
-import com.sun.jdi.connect.Connector;
 import com.sun.jdi.event.BreakpointEvent;
 import com.sun.jdi.event.Event;
 import com.sun.jdi.event.EventSet;
@@ -10,34 +8,24 @@ import com.sun.jdi.event.LocatableEvent;
 import com.sun.jdi.request.BreakpointRequest;
 import lombok.AccessLevel;
 import lombok.RequiredArgsConstructor;
+import net.ranides.demo.debugger.DiClass;
+import net.ranides.demo.debugger.DiConnection;
 
 import java.util.Arrays;
 import java.util.List;
-import java.util.Map;
 import java.util.stream.Collectors;
 
 public class SimpleDebugger implements AutoCloseable {
 
-    private VirtualMachine vm;
+    private DiConnection di;
 
     public SimpleDebugger connect(String port) throws Exception {
-        return connect("localhost", port);
+        di = DiConnection.connect(port);
+        return this;
     }
 
     public SimpleDebugger connect(String host, String port) throws Exception {
-        AttachingConnector connector = Bootstrap.virtualMachineManager()
-            .attachingConnectors()
-            .stream()
-            .filter(v -> v.name().equals("com.sun.jdi.SocketAttach"))
-            .findFirst()
-            .orElseThrow(() -> new UnsupportedOperationException("No SocketAttachingConnector found."));
-
-        Map<String, Connector.Argument> args = connector.defaultArguments();
-        args.get("hostname").setValue(host);
-        args.get("port").setValue(port);
-
-        this.vm = connector.attach(args);
-
+        di = DiConnection.connect(host, port);
         return this;
     }
 
@@ -51,22 +39,17 @@ public class SimpleDebugger implements AutoCloseable {
     }
 
     public BreakpointRequest breakpoint(RemoteLocation remote) throws Exception {
-        ClassType type = vm.classesByName(remote.className)
-            .stream()
-            .filter(ClassType.class::isInstance)
-            .map(ClassType.class::cast)
-            .findAny()
+        DiClass type = di.types(remote.className).first()
             .orElseThrow(() -> new IllegalArgumentException("Unknown class: " + remote.className));
 
-        Location location = type.locationsOfLine(remote.line).get(0);
-        BreakpointRequest breakpoint = vm.eventRequestManager().createBreakpointRequest(location);
+        BreakpointRequest breakpoint = type.locate(remote.line).breakpoint();
         breakpoint.enable();
         return breakpoint;
     }
 
     public <T> T loop(LoopHandler<T> handler) throws Exception {
         EventSet eventSet;
-        while ((eventSet = vm.eventQueue().remove()) != null) {
+        while ((eventSet = di.vm().eventQueue().remove()) != null) {
             for (Event event : eventSet) {
                 try {
                     LoopContext context = new LoopContext(event);
@@ -79,7 +62,7 @@ public class SimpleDebugger implements AutoCloseable {
                 } catch (Exception error) {
                     throw new RuntimeException(error);
                 } finally {
-                    vm.resume();
+                    di.vm().resume();
                 }
             }
         }
@@ -93,13 +76,13 @@ public class SimpleDebugger implements AutoCloseable {
             throw new IllegalArgumentException("Unknown variable: " + name);
         }
         Value mirror = frame.getValue(variable);
-        return fromMirror(mirror);
+        return di.mirror().asPrimitive(mirror);
     }
 
     private Object call0(LocatableEvent event, String methodName, Object[] arguments) throws Exception {
-        List<Value> input = Arrays.stream(arguments).map(this::mirrorOf).collect(Collectors.toList());
+        List<Value> input = Arrays.stream(arguments).map(di.mirror()::asMirror).collect(Collectors.toList());
         Value out = call0(event, methodName, input);
-        return fromMirror(out);
+        return di.mirror().asPrimitive(out);
     }
 
     private Value call0(LocatableEvent event, String methodName, List<? extends Value> arguments) throws Exception {
@@ -114,69 +97,7 @@ public class SimpleDebugger implements AutoCloseable {
 
     @Override
     public void close() {
-        vm.dispose();
-    }
-
-    public Value mirrorOf(Object value) {
-        if (value instanceof String) {
-            return vm.mirrorOf((String) value);
-        }
-        if (value instanceof Integer) {
-            return vm.mirrorOf((Integer) value);
-        }
-        if (value instanceof Short) {
-            return vm.mirrorOf((Short) value);
-        }
-        if (value instanceof Byte) {
-            return vm.mirrorOf((Byte) value);
-        }
-        if (value instanceof Long) {
-            return vm.mirrorOf((Long) value);
-        }
-        if (value instanceof Float) {
-            return vm.mirrorOf((Float) value);
-        }
-        if (value instanceof Double) {
-            return vm.mirrorOf((Double) value);
-        }
-        if (value instanceof Boolean) {
-            return vm.mirrorOf((Boolean) value);
-        }
-        if (value instanceof Character) {
-            return vm.mirrorOf((Character) value);
-        }
-        throw new IllegalArgumentException("Not supported value: " + value);
-    }
-
-    public Object fromMirror(Value value) {
-        if (value instanceof StringReference) {
-            return ((StringReference) value).value();
-        }
-        if (value instanceof IntegerValue) {
-            return ((IntegerValue) value).value();
-        }
-        if (value instanceof ShortValue) {
-            return ((ShortValue) value).value();
-        }
-        if (value instanceof ByteValue) {
-            return ((ByteValue) value).value();
-        }
-        if (value instanceof LongValue) {
-            return ((LongValue) value).value();
-        }
-        if (value instanceof FloatValue) {
-            return ((FloatValue) value).value();
-        }
-        if (value instanceof DoubleValue) {
-            return ((DoubleValue) value).value();
-        }
-        if (value instanceof BooleanValue) {
-            return ((BooleanValue) value).value();
-        }
-        if (value instanceof CharValue) {
-            return ((CharValue) value).value();
-        }
-        throw new IllegalArgumentException("Not supported value: " + value);
+        di.vm().dispose();
     }
 
     public class RemoteLocation {
@@ -240,7 +161,7 @@ public class SimpleDebugger implements AutoCloseable {
             return event instanceof LocatableEvent;
         }
 
-        public boolean matches(RemoteLocation location) throws Exception {
+        public boolean matches(RemoteLocation location) {
             return isLocatable() && location.matches((LocatableEvent)event);
         }
 
@@ -268,7 +189,7 @@ public class SimpleDebugger implements AutoCloseable {
             return event;
         }
 
-        public boolean matches(RemoteLocation location) throws Exception {
+        public boolean matches(RemoteLocation location) {
             return location.matches(event);
         }
 

+ 1 - 1
assira.debugger/src/test/java/net/ranides/demo/debugger/AppDebugger.java

@@ -1,8 +1,8 @@
 package net.ranides.demo.debugger;
 
 import com.sun.jdi.VMDisconnectedException;
-import com.sun.jdi.event.LocatableEvent;
 import com.sun.jdi.request.BreakpointRequest;
+import net.ranides.demo.debugger.util.SimpleDebugger;
 
 import java.util.Optional;