Add better support for conditional expressions for breakpoints
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/SmaliCodeFragmentFactory.java b/smalidea/src/main/java/org/jf/smalidea/debugging/SmaliCodeFragmentFactory.java
index 3a84af8..469d27b 100644
--- a/smalidea/src/main/java/org/jf/smalidea/debugging/SmaliCodeFragmentFactory.java
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/SmaliCodeFragmentFactory.java
@@ -31,17 +31,18 @@
 
 package org.jf.smalidea.debugging;
 
+import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
-import com.intellij.debugger.DebuggerManagerEx;
-import com.intellij.debugger.engine.DebugProcessImpl;
+import com.intellij.debugger.SourcePosition;
 import com.intellij.debugger.engine.evaluation.*;
-import com.intellij.debugger.engine.events.DebuggerCommandImpl;
-import com.intellij.debugger.impl.DebuggerContextImpl;
-import com.intellij.debugger.jdi.StackFrameProxyImpl;
+import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilder;
+import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator;
+import com.intellij.debugger.engine.jdi.StackFrameProxy;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.fileTypes.LanguageFileType;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Key;
 import com.intellij.psi.JavaCodeFragment;
 import com.intellij.psi.JavaRecursiveElementVisitor;
 import com.intellij.psi.PsiElement;
@@ -54,18 +55,28 @@
 import org.jf.dexlib2.analysis.RegisterType;
 import org.jf.smalidea.SmaliFileType;
 import org.jf.smalidea.SmaliLanguage;
+import org.jf.smalidea.debugging.value.LazyValue;
 import org.jf.smalidea.psi.impl.SmaliInstruction;
 import org.jf.smalidea.psi.impl.SmaliMethod;
 import org.jf.smalidea.util.PsiUtil;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import java.util.List;
 import java.util.Map;
 
 public class SmaliCodeFragmentFactory extends DefaultCodeFragmentFactory {
+    static final Key<List<LazyValue>> SMALI_LAZY_VALUES_KEY = Key.create("_smali_register_value_key_");
+
     @Override
     public JavaCodeFragment createCodeFragment(TextWithImports item, PsiElement context, Project project) {
-        return super.createCodeFragment(item, wrapContext(project, context), project);
+        context = wrapContext(project, context);
+        JavaCodeFragment fragment = super.createCodeFragment(item, context, project);
+        List<LazyValue> lazyValues = context.getUserData(SMALI_LAZY_VALUES_KEY);
+        if (lazyValues != null) {
+            fragment.putUserData(SMALI_LAZY_VALUES_KEY, lazyValues);
+        }
+        return fragment;
     }
 
     @Override
@@ -78,17 +89,35 @@
 
     @Override
     public JavaCodeFragment createPresentationCodeFragment(TextWithImports item, PsiElement context, Project project) {
-        return super.createPresentationCodeFragment(item, wrapContext(project, context), project);
+        context = wrapContext(project, context);
+        JavaCodeFragment fragment = super.createPresentationCodeFragment(item, context, project);
+        List<LazyValue> lazyValues = context.getUserData(SMALI_LAZY_VALUES_KEY);
+        if (lazyValues != null) {
+            fragment.putUserData(SMALI_LAZY_VALUES_KEY, lazyValues);
+        }
+        return fragment;
     }
 
     @Override public LanguageFileType getFileType() {
         return SmaliFileType.INSTANCE;
     }
 
+    @Override public EvaluatorBuilder getEvaluatorBuilder() {
+        final EvaluatorBuilder builder = super.getEvaluatorBuilder();
+        return new EvaluatorBuilder() {
+
+            @Override
+            public ExpressionEvaluator build(PsiElement codeFragment, SourcePosition position)
+                    throws EvaluateException {
+                return new SmaliExpressionEvaluator(codeFragment, builder.build(codeFragment, position));
+            }
+        };
+    }
+
     private PsiElement wrapContext(final Project project, final PsiElement originalContext) {
         if (project.isDefault()) return originalContext;
 
-        final DebuggerContextImpl debuggerContext = DebuggerManagerEx.getInstanceEx(project).getContext();
+        final List<LazyValue> lazyValues = Lists.newArrayList();
 
         SmaliInstruction currentInstruction = (SmaliInstruction)PsiUtil.searchBackward(originalContext,
                 PsiMatchers.hasClass(SmaliInstruction.class),
@@ -215,29 +244,19 @@
             public void visitLocalVariable(final PsiLocalVariable variable) {
                 final String name = variable.getName();
                 if (registerMap.containsKey(name)) {
-                    DebugProcessImpl process = debuggerContext.getDebugProcess();
-                    if (process == null) {
-                        return;
-                    }
-
-                    process.getManagerThread().invoke(new DebuggerCommandImpl() {
-                        @Override protected void action() throws Exception {
-                            int registerNumber = Integer.parseInt(name.substring(1));
-                            if (name.charAt(0) == 'p') {
-                                registerNumber += ApplicationManager.getApplication().runReadAction(new Computable<Integer>() {
-                                    @Override public Integer compute() {
-                                        return containingMethod.getRegisterCount() -
-                                                containingMethod.getParameterRegisterCount();
-                                    }
-                                });
+                    int registerNumber = Integer.parseInt(name.substring(1));
+                    if (name.charAt(0) == 'p') {
+                        registerNumber += ApplicationManager.getApplication().runReadAction(new Computable<Integer>() {
+                            @Override public Integer compute() {
+                                return containingMethod.getRegisterCount() -
+                                        containingMethod.getParameterRegisterCount();
                             }
-                            Value value = evaluateRegister(debuggerContext.createEvaluationContext(),
-                                    containingMethod,
-                                    registerNumber,
-                                    registerMap.get(name));
-                            variable.putUserData(CodeFragmentFactoryContextWrapper.LABEL_VARIABLE_VALUE_KEY, value);
-                        }
-                    });
+                        });
+                    }
+                    LazyValue lazyValue = LazyValue.create(containingMethod, project, registerNumber,
+                            registerMap.get(name));
+                    variable.putUserData(CodeFragmentFactoryContextWrapper.LABEL_VARIABLE_VALUE_KEY, lazyValue);
+                    lazyValues.add(lazyValue);
                 }
             }
         });
@@ -246,22 +265,21 @@
 
         final PsiElement newContext = codeFragment.findElementAt(offset);
         if (newContext != null) {
+            newContext.putUserData(SMALI_LAZY_VALUES_KEY, lazyValues);
             return newContext;
         }
         return originalContext;
     }
 
-    public Value evaluateRegister(EvaluationContextImpl context, final SmaliMethod smaliMethod, final int registerNum,
-                                  final String type) throws EvaluateException {
-        final StackFrameProxyImpl frameProxy = context.getFrameProxy();
+    public static Value evaluateRegister(EvaluationContext context, final SmaliMethod smaliMethod,
+                                         final int registerNum, final String type) throws EvaluateException {
+
+        final StackFrameProxy frameProxy = context.getSuspendContext().getFrameProxy();
         if (frameProxy == null) {
             return null;
         }
 
-        // the jdi APIs don't provide any way to get the value of an arbitrary register, so we use reflection
-        // to create a LocalVariable instance for the register
-
-        VirtualMachine vm = frameProxy.getVirtualMachine().getVirtualMachine();
+        VirtualMachine vm = frameProxy.getStackFrame().virtualMachine();
         Location currentLocation = frameProxy.location();
         if (currentLocation == null) {
             return null;
@@ -279,8 +297,11 @@
                     VirtualMachine.class, Method.class, Long.TYPE);
             locationConstructor.setAccessible(true);
 
-            // TODO: use frameProxy.location().method().locationOfCodeIndex() here
-            Location endLocation = locationConstructor.newInstance(vm, method, Integer.MAX_VALUE);
+            int methodSize = 0;
+            for (SmaliInstruction instruction: smaliMethod.getInstructions()) {
+                methodSize += instruction.getInstructionSize();
+            }
+            Location endLocation = method.locationOfCodeIndex((methodSize/2) - 1);
 
             LocalVariable localVariable = localVariableConstructor.newInstance(vm,
                     method,
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/SmaliExpressionEvaluator.java b/smalidea/src/main/java/org/jf/smalidea/debugging/SmaliExpressionEvaluator.java
new file mode 100644
index 0000000..89bba29
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/SmaliExpressionEvaluator.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging;
+
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.EvaluationContext;
+import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator;
+import com.intellij.debugger.engine.evaluation.expression.Modifier;
+import com.intellij.psi.PsiElement;
+import com.sun.jdi.Value;
+import org.jf.smalidea.debugging.value.LazyValue;
+
+import java.util.List;
+
+public class SmaliExpressionEvaluator implements ExpressionEvaluator {
+    private final PsiElement fragment;
+    private final ExpressionEvaluator evaluator;
+
+    public SmaliExpressionEvaluator(PsiElement fragment, ExpressionEvaluator evaluator) {
+        this.fragment = fragment;
+        this.evaluator = evaluator;
+    }
+
+    @Override public Value evaluate(EvaluationContext context) throws EvaluateException {
+        List<LazyValue> lazyValues = fragment.getUserData(SmaliCodeFragmentFactory.SMALI_LAZY_VALUES_KEY);
+        if (lazyValues != null) {
+            for (LazyValue lazyValue: lazyValues) {
+                lazyValue.setEvaluationContext(context);
+            }
+        }
+        return evaluator.evaluate(context);
+    }
+
+    @Override public Value getValue() {
+        return evaluator.getValue();
+    }
+
+    @Override public Modifier getModifier() {
+        return evaluator.getModifier();
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyArrayReference.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyArrayReference.java
new file mode 100644
index 0000000..ad55a9f
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyArrayReference.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.ArrayReference;
+import com.sun.jdi.ClassNotLoadedException;
+import com.sun.jdi.InvalidTypeException;
+import com.sun.jdi.Value;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+import java.util.List;
+
+public class LazyArrayReference extends LazyObjectReference<ArrayReference> implements ArrayReference {
+    public LazyArrayReference(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    public Value getValue(int index) {
+        return getValue().getValue(index);
+    }
+
+    public List<Value> getValues() {
+        return getValue().getValues();
+    }
+
+    public List<Value> getValues(int index, int length) {
+        return getValue().getValues(index, length);
+    }
+
+    public int length() {
+        return getValue().length();
+    }
+
+    public void setValue(int index, Value value) throws InvalidTypeException, ClassNotLoadedException {
+        getValue().setValue(index, value);
+    }
+
+    public void setValues(int index, List<? extends Value> values, int srcIndex, int length) throws InvalidTypeException, ClassNotLoadedException {
+        getValue().setValues(index, values, srcIndex, length);
+    }
+
+    public void setValues(List<? extends Value> values) throws InvalidTypeException, ClassNotLoadedException {
+        getValue().setValues(values);
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyBooleanValue.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyBooleanValue.java
new file mode 100644
index 0000000..e42da25
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyBooleanValue.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.BooleanValue;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+public class LazyBooleanValue extends LazyPrimitiveValue<BooleanValue> implements BooleanValue {
+    public LazyBooleanValue(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    @Override public boolean value() {
+        return getValue().value();
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyByteValue.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyByteValue.java
new file mode 100644
index 0000000..bc0e6a3
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyByteValue.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.ByteValue;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+public class LazyByteValue extends LazyComparablePrimitiveValue<ByteValue> implements ByteValue {
+    public LazyByteValue(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    @Override public byte value() {
+        return getValue().value();
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyCharValue.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyCharValue.java
new file mode 100644
index 0000000..0c536dd
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyCharValue.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.CharValue;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+public class LazyCharValue extends LazyComparablePrimitiveValue<CharValue> implements CharValue {
+    public LazyCharValue(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    @Override public char value() {
+        return getValue().value();
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyClassLoaderReference.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyClassLoaderReference.java
new file mode 100644
index 0000000..dc41bbb
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyClassLoaderReference.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.ClassLoaderReference;
+import com.sun.jdi.ReferenceType;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+import java.util.List;
+
+public class LazyClassLoaderReference extends LazyObjectReference<ClassLoaderReference>
+        implements ClassLoaderReference {
+    public LazyClassLoaderReference(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    public List<ReferenceType> definedClasses() {
+        return getValue().definedClasses();
+    }
+
+    public List<ReferenceType> visibleClasses() {
+        return getValue().visibleClasses();
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyClassObjectReference.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyClassObjectReference.java
new file mode 100644
index 0000000..62ac420
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyClassObjectReference.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.ClassObjectReference;
+import com.sun.jdi.ReferenceType;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+public class LazyClassObjectReference extends LazyObjectReference<ClassObjectReference>
+        implements ClassObjectReference {
+    public LazyClassObjectReference(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    public ReferenceType reflectedType() {
+        return getValue().reflectedType();
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyComparablePrimitiveValue.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyComparablePrimitiveValue.java
new file mode 100644
index 0000000..e4a0b33
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyComparablePrimitiveValue.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.PrimitiveValue;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+public class LazyComparablePrimitiveValue<T extends PrimitiveValue & Comparable<T>> extends LazyPrimitiveValue<T>
+        implements Comparable<T> {
+    public LazyComparablePrimitiveValue(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    public int compareTo(T o) {
+        return getValue().compareTo(o);
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyDoubleValue.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyDoubleValue.java
new file mode 100644
index 0000000..ae9e17a
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyDoubleValue.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.DoubleValue;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+public class LazyDoubleValue extends LazyComparablePrimitiveValue<DoubleValue> implements DoubleValue {
+    public LazyDoubleValue(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    @Override public double value() {
+        return getValue().value();
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyFloatValue.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyFloatValue.java
new file mode 100644
index 0000000..54041cd
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyFloatValue.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.FloatValue;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+public class LazyFloatValue extends LazyComparablePrimitiveValue<FloatValue> implements FloatValue {
+    public LazyFloatValue(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    @Override public float value() {
+        return getValue().value();
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyIntegerValue.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyIntegerValue.java
new file mode 100644
index 0000000..87b13ca
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyIntegerValue.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.IntegerValue;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+public class LazyIntegerValue extends LazyComparablePrimitiveValue<IntegerValue> implements IntegerValue {
+    public LazyIntegerValue(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    @Override public int value() {
+        return getValue().value();
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyLongValue.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyLongValue.java
new file mode 100644
index 0000000..e1c1aaf
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyLongValue.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.LongValue;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+public class LazyLongValue extends LazyComparablePrimitiveValue<LongValue> implements LongValue {
+    public LazyLongValue(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    @Override public long value() {
+        return getValue().value();
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyObjectReference.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyObjectReference.java
new file mode 100644
index 0000000..9f50bf3
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyObjectReference.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.*;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+import java.util.List;
+import java.util.Map;
+
+public class LazyObjectReference<T extends ObjectReference> extends LazyValue<T> implements ObjectReference {
+
+    public LazyObjectReference(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    @Override public void disableCollection() {
+        getValue().disableCollection();
+    }
+
+    @Override public ReferenceType referenceType() {
+        return getValue().referenceType();
+    }
+
+    @Override public Value getValue(Field sig) {
+        return getValue().getValue(sig);
+    }
+
+    @Override public Map<Field, Value> getValues(List<? extends Field> fields) {
+        return getValue().getValues(fields);
+    }
+
+    @Override public void setValue(Field field, Value value) throws InvalidTypeException, ClassNotLoadedException {
+        getValue().setValue(field, value);
+    }
+
+    @Override
+    public Value invokeMethod(ThreadReference thread, Method method, List<? extends Value> arguments, int options)
+            throws InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException,
+            InvocationException {
+        return getValue().invokeMethod(thread, method, arguments, options);
+    }
+
+    @Override public void enableCollection() {
+        getValue().enableCollection();
+    }
+
+    @Override public boolean isCollected() {
+        return getValue().isCollected();
+    }
+
+    @Override public long uniqueID() {
+        return getValue().uniqueID();
+    }
+
+    @Override public List<ThreadReference> waitingThreads() throws IncompatibleThreadStateException {
+        return getValue().waitingThreads();
+    }
+
+    @Override public ThreadReference owningThread() throws IncompatibleThreadStateException {
+        return getValue().owningThread();
+    }
+
+    @Override public int entryCount() throws IncompatibleThreadStateException {
+        return getValue().entryCount();
+    }
+
+    @Override public List<ObjectReference> referringObjects(long maxReferrers) {
+        return getValue().referringObjects(maxReferrers);
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyPrimitiveValue.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyPrimitiveValue.java
new file mode 100644
index 0000000..65d3635
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyPrimitiveValue.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.PrimitiveValue;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+public class LazyPrimitiveValue<T extends PrimitiveValue> extends LazyValue<T> implements PrimitiveValue {
+    public LazyPrimitiveValue(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    @Override public boolean booleanValue() {
+        return getValue().booleanValue();
+    }
+
+    @Override public byte byteValue() {
+        return getValue().byteValue();
+    }
+
+    @Override public char charValue() {
+        return getValue().charValue();
+    }
+
+    @Override public double doubleValue() {
+        return getValue().doubleValue();
+    }
+
+    @Override public float floatValue() {
+        return getValue().floatValue();
+    }
+
+    @Override public int intValue() {
+        return getValue().intValue();
+    }
+
+    @Override public long longValue() {
+        return getValue().longValue();
+    }
+
+    @Override public short shortValue() {
+        return getValue().shortValue();
+    }
+
+    @Override public String toString() {
+        return getValue().toString();
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyShortValue.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyShortValue.java
new file mode 100644
index 0000000..10a5fa3
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyShortValue.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.ShortValue;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+public class LazyShortValue extends LazyComparablePrimitiveValue<ShortValue> implements ShortValue {
+    public LazyShortValue(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    @Override public short value() {
+        return getValue().value();
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyStringReference.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyStringReference.java
new file mode 100644
index 0000000..88fd007
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyStringReference.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.StringReference;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+public class LazyStringReference extends LazyObjectReference<StringReference> implements StringReference {
+    public LazyStringReference(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    public String value() {
+        return getValue().value();
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyThreadGroupReference.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyThreadGroupReference.java
new file mode 100644
index 0000000..05f05d6
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyThreadGroupReference.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.ThreadGroupReference;
+import com.sun.jdi.ThreadReference;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+import java.util.List;
+
+public class LazyThreadGroupReference extends LazyObjectReference<ThreadGroupReference>
+        implements ThreadGroupReference {
+
+    public LazyThreadGroupReference(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    @Override public String name() {
+        return getValue().name();
+    }
+
+    @Override public ThreadGroupReference parent() {
+        return getValue().parent();
+    }
+
+    @Override public void resume() {
+        getValue().resume();
+    }
+
+    @Override public void suspend() {
+        getValue().suspend();
+    }
+
+    @Override public List<ThreadGroupReference> threadGroups() {
+        return getValue().threadGroups();
+    }
+
+    @Override public List<ThreadReference> threads() {
+        return getValue().threads();
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyThreadReference.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyThreadReference.java
new file mode 100644
index 0000000..61a13f8
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyThreadReference.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.*;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+import java.util.List;
+
+public class LazyThreadReference extends LazyObjectReference<ThreadReference> implements ThreadReference {
+    public LazyThreadReference(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+
+    public ObjectReference currentContendedMonitor() throws IncompatibleThreadStateException {
+        return getValue().currentContendedMonitor();
+    }
+
+    public void forceEarlyReturn(Value value) throws InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException {
+        getValue().forceEarlyReturn(value);
+    }
+
+    public StackFrame frame(int index) throws IncompatibleThreadStateException {
+        return getValue().frame(index);
+    }
+
+    public int frameCount() throws IncompatibleThreadStateException {
+        return getValue().frameCount();
+    }
+
+    public List<StackFrame> frames() throws IncompatibleThreadStateException {
+        return getValue().frames();
+    }
+
+    public List<StackFrame> frames(int start, int length) throws IncompatibleThreadStateException {
+        return getValue().frames(start, length);
+    }
+
+    public void interrupt() {
+        getValue().interrupt();
+    }
+
+    public boolean isAtBreakpoint() {
+        return getValue().isAtBreakpoint();
+    }
+
+    public boolean isSuspended() {
+        return getValue().isSuspended();
+    }
+
+    public String name() {
+        return getValue().name();
+    }
+
+    public List<ObjectReference> ownedMonitors() throws IncompatibleThreadStateException {
+        return getValue().ownedMonitors();
+    }
+
+    public List<MonitorInfo> ownedMonitorsAndFrames() throws IncompatibleThreadStateException {
+        return getValue().ownedMonitorsAndFrames();
+    }
+
+    public void popFrames(StackFrame frame) throws IncompatibleThreadStateException {
+        getValue().popFrames(frame);
+    }
+
+    public void resume() {
+        getValue().resume();
+    }
+
+    public int status() {
+        return getValue().status();
+    }
+
+    public void stop(ObjectReference throwable) throws InvalidTypeException {
+        getValue().stop(throwable);
+    }
+
+    public void suspend() {
+        getValue().suspend();
+    }
+
+    public int suspendCount() {
+        return getValue().suspendCount();
+    }
+
+    public ThreadGroupReference threadGroup() {
+        return getValue().threadGroup();
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyValue.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyValue.java
new file mode 100644
index 0000000..746a629
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyValue.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.debugger.DebuggerManagerEx;
+import com.intellij.debugger.engine.DebugProcessImpl;
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.EvaluationContext;
+import com.intellij.debugger.impl.DebuggerContextImpl;
+import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.Type;
+import com.sun.jdi.Value;
+import com.sun.jdi.VirtualMachine;
+import org.jf.smalidea.debugging.SmaliCodeFragmentFactory;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+public class LazyValue<T extends Value> implements Value {
+    private final int registerNumber;
+    private final Project project;
+    private final SmaliMethod method;
+    private final String type;
+
+    private EvaluationContext evaluationContext;
+    private Value value;
+
+    public LazyValue(SmaliMethod method, Project project, int registerNumber, String type) {
+        this.method = method;
+        this.project = project;
+        this.registerNumber = registerNumber;
+        this.type = type;
+    }
+
+    public static LazyValue create(@Nonnull SmaliMethod method, @Nonnull Project project, int registerNumber,
+                                   @Nonnull String type) {
+        if (type.equals("B")) {
+            return new LazyByteValue(method, project, registerNumber, type);
+        } else if (type.equals("S")) {
+            return new LazyShortValue(method, project, registerNumber, type);
+        } else if (type.equals("J")) {
+            return new LazyLongValue(method, project, registerNumber, type);
+        } else if (type.equals("I")) {
+            return new LazyIntegerValue(method, project, registerNumber, type);
+        } else if (type.equals("F")) {
+            return new LazyFloatValue(method, project, registerNumber, type);
+        } else if (type.equals("D")) {
+            return new LazyDoubleValue(method, project, registerNumber, type);
+        } else if (type.equals("Z")) {
+            return new LazyBooleanValue(method, project, registerNumber, type);
+        } else if (type.equals("C")) {
+            return new LazyCharValue(method, project, registerNumber, type);
+        } else if (type.equals("V")) {
+            return new LazyVoidValue(method, project, registerNumber, type);
+        } else if (type.startsWith("[")) {
+            return new LazyArrayReference(method, project, registerNumber, type);
+        } else if (type.equals("Ljava/lang/String;")) {
+            return new LazyStringReference(method, project, registerNumber, type);
+        } else if (type.equals("Ljava/lang/Class;")) {
+            return new LazyClassObjectReference(method, project, registerNumber, type);
+        } else if (type.equals("Ljava/lang/ThreadGroup;")) {
+            return new LazyThreadGroupReference(method, project, registerNumber, type);
+        } else if (type.equals("Ljava/lang/Thread;")) {
+            return new LazyThreadReference(method, project, registerNumber, type);
+        } else if (type.equals("Ljava/lang/ClassLoader;")) {
+            return new LazyClassLoaderReference(method, project, registerNumber, type);
+        } else if (type.startsWith("L")) {
+            return new LazyObjectReference(method, project, registerNumber, type);
+        }
+        return new LazyValue(method, project, registerNumber, type);
+    }
+
+    @Nullable
+    private T getNullableValue() {
+        if (value == null) {
+            try {
+                if (evaluationContext == null) {
+                    final DebuggerContextImpl debuggerContext = DebuggerManagerEx.getInstanceEx(project).getContext();
+                    evaluationContext = debuggerContext.createEvaluationContext();
+                    if (evaluationContext == null) {
+                        return null;
+                    }
+                }
+
+                value = SmaliCodeFragmentFactory.evaluateRegister(evaluationContext, method, registerNumber, type);
+                evaluationContext = null;
+            } catch (EvaluateException ex) {
+                return null;
+            }
+        }
+        return (T)value;
+    }
+
+    @Nonnull
+    protected T getValue() {
+        T value = getNullableValue();
+        assert value != null;
+        return value;
+    }
+
+    @Override
+    public Type type() {
+        return getValue().type();
+    }
+
+    @Override
+    public VirtualMachine virtualMachine() {
+        if (evaluationContext != null) {
+            return ((VirtualMachineProxyImpl)evaluationContext.getDebugProcess().getVirtualMachineProxy())
+                    .getVirtualMachine();
+        } else {
+            final DebuggerContextImpl debuggerContext = DebuggerManagerEx.getInstanceEx(project).getContext();
+            final DebugProcessImpl process = debuggerContext.getDebugProcess();
+            if (process != null) {
+                return process.getVirtualMachineProxy().getVirtualMachine();
+            }
+        }
+        return null;
+    }
+
+    public void setEvaluationContext(@Nonnull EvaluationContext evaluationContext) {
+        this.evaluationContext = evaluationContext;
+    }
+
+    @Override public boolean equals(Object obj) {
+        Value value = getNullableValue();
+        if (value != null) {
+            return value.equals(obj);
+        }
+        return super.equals(obj);
+    }
+
+    @Override public int hashCode() {
+        Value value = getNullableValue();
+        if (value != null) {
+            return value.hashCode();
+        }
+        return super.hashCode();
+    }
+
+    @Override public String toString() {
+        Value value = getNullableValue();
+        if (value != null) {
+            return value.toString();
+        }
+        return super.toString();
+    }
+}
diff --git a/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyVoidValue.java b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyVoidValue.java
new file mode 100644
index 0000000..a7f6bdc
--- /dev/null
+++ b/smalidea/src/main/java/org/jf/smalidea/debugging/value/LazyVoidValue.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea.debugging.value;
+
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.VoidValue;
+import org.jf.smalidea.psi.impl.SmaliMethod;
+
+public class LazyVoidValue extends LazyValue<VoidValue> implements VoidValue {
+    public LazyVoidValue(SmaliMethod method, Project project, int registerNumber, String type) {
+        super(method, project, registerNumber, type);
+    }
+}