Last active
August 29, 2015 14:23
-
-
Save alb-i986/dcdc682c9239457ffa5e to your computer and use it in GitHub Desktop.
Debuggers. Inspecting variables with self references
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package debugger.test; | |
import org.junit.Test; | |
/** | |
* To show a "weird" behavior of Intellij IDEA and Eclipse debuggers. | |
* | |
* Here we have the class SelfObj that has a field that is a self reference. | |
* | |
* Set the breakpoint at the line shown, and inspect the variable selfObj. | |
* Expand the field of the variable. | |
* You will be able to expand it again. And again. And again... (recursion). | |
* | |
* This is something I found out while debugging some tests, and inspecting the exceptions. | |
* Throwable, in fact, has a cause that is by default a self reference. | |
*/ | |
public class SelfRefDebuggerTest { | |
@Test | |
public void test() { | |
SelfObj selfObj = new SelfObj(); | |
System.out.println(selfObj); // set a breakpoint at this line | |
// inspecting the var selfObj in the debugger | |
} | |
public static class SelfObj { | |
SelfObj self; | |
int integer = 10; | |
public SelfObj() { | |
this.self = this; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.reflect.Field; | |
/** | |
* A fully working, yet simplistic, inspector of variables | |
* written for https://youtrack.jetbrains.com/issue/IDEABKL-7249 | |
* | |
* It features a recursive function which loops over the fields of an object. | |
* | |
* The main point is this: | |
* when it encounters a variable with a field whose value is `this`, | |
* then it breaks the recursion (which would be an infinite loop, actually). | |
* | |
* @author alb-i986 | |
*/ | |
public class VarInspector { | |
private static final int ROOT_INDENT_LEVEL = 1; | |
public static void main(String[] args) throws IllegalAccessException { | |
drawVar(new SelfObj()); | |
} | |
public static void drawVar(Object var) throws IllegalAccessException { | |
drawVarRecursive(var, ROOT_INDENT_LEVEL); | |
} | |
private static void drawVarRecursive(Object var, int level) throws IllegalAccessException { | |
printValueIndented(var, level - 1); | |
Field[] fields = var.getClass().getDeclaredFields(); | |
// recursion base case | |
if (fields.length == 0) { | |
return; | |
} | |
for (Field field : fields) { | |
Object fieldValue = field.get(var); | |
// break the recursion if var has a field whose value is `this` | |
if (fieldValue == var) { | |
printFieldIndented(field, var, level); | |
continue; | |
} | |
// if field is an int, Field#get returns an Integer, so we need a special case | |
if (fieldValue instanceof Integer) { | |
printFieldIndented(field, var, level); | |
continue; | |
} | |
// more special cases should be added, at least one for each primitive type... | |
// ..but skipping for our simple case study | |
drawVarRecursive(fieldValue, level + 1); | |
} | |
} | |
private static void printFieldIndented(Field field, Object var, int level) throws IllegalAccessException { | |
Object fieldValue = field.get(var); | |
printIndented(field.getName() + ": " + String.valueOf(fieldValue), level); | |
} | |
private static void printValueIndented(Object value, int level) { | |
printIndented(String.valueOf(value), level); | |
} | |
private static void printIndented(String string, int level) { | |
String indent = ""; | |
for (int i = 0 ; i<level ; i++) { | |
indent += " "; | |
} | |
System.out.println(indent + string); | |
} | |
public static class SelfObj { | |
SelfObj selfField = this; | |
int integerField = 1; | |
NonSelfObj nonSelfObjField = new NonSelfObj(); | |
} | |
public static class NonSelfObj { | |
int numField = 2; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment