eval4j - Oracle

eval4j compiling expressions to be evaluated by the debugger andrey.breslav@
.com
Stop at a breakpoint Inspect call stacks Inspect memory Evaluate given Evaluate given expression expression Debugger Features •  Stopping at breakpoints –  step over/into/out •  Inspec?ng memory contents –  variables on stack –  object fields/array cells •  Evalua?ng expressions –  watches –  condi?onal breakpoints –  logging breakpoints Working Horse: Bare JDI •  Access Variables •  Access Fields •  Call Methods •  No Evaluate Expression out-­‐of-­‐the-­‐box How it’s done for Java •  IntelliJ has an intepreter for Java expressions –  wriOen from scratch –  yet another defini?on of seman?cs –  may disagree with the compiler’s seman?cs •  Well, IntelliJ’s not very in?mate with javac
When you have your own compiler? •  Eclipse Java DT s?ll has an interpreter •  Scala IDE (Eclipse) — no Evaluate Expression •  Ceylon IDE (Eclipse) — no Evaluate Expression •  There’s some room for improvement… What we don’t want •  Re-­‐implement the seman?cs just for this task –  Use what we already have –  In case of Kotlin/Java/Scala – the compiler What actually happens for Java •  IntelliJ – interpreter for Java expressions –  Understandable: javac is run as an external process •  NetBeans – dedicated interpreter –  Umm… •  Eclipse – dedicated interpreter –  Huh? What happens for others •  Scala –  IntelliJ – dedicated interpreter •  Same story: scalac is an external process –  Eclipse – Evaluate Expression is not supported •  Ceylon –  ??? Reuse the Compiler (Take 1) a + b compile .class file load run Debugee process Eval4j: Bytecode Interpreter •  foo.x + 2 – 
– 
– 
– 
ALOAD 1
GETFIELD Foo.x : I
ICONST_2
IADD
–  INVOKESTATIC kotlin/io/IoPackage.println (I)V •  hOps://github.com/abreslav/eval4j •  Re-­‐uses ASM’s Interpreter Compiling an expression free variables Extract Method Refactoring Summary so far Extract Method + Compiler + eval4j = Evaluate Expression Challenge: Lambdas/Anonymous Classes •  Not supported for Java/Scala •  Problems: –  New class that is not available in the debugee process –  That class may access privates that it’s not allowed to access Challenge: New Classes private? •  Also: How do you load a class into the debugee? Loading a class… •  protected Class<?> defineClass(byte[], …) How Privates Work Normally •  Special synthe?c accessor methods –  INVOKESTATIC Foo.access$001()
–  can’t insert a new method into the outer class Prepare the methods of the lambda •  Evaluate the body of the method public Object invoke() {
Object result = null;
Throwable exception = null;
if (exception == null)
return result;
else throw exception;
}
What happens to your thread •  You stopped on a bp1 •  You evaluated an expression –  Set another bp –  Stopped on it –  Computed something –  Resulmed –  => you are not on bp1 any more Workaround •  Start a special thread while (true) {
nop();
}
•  To stop: boolean done = false;
while (!done) {
nop();
}
Summary •  Prerequisites –  Extract method –  Ability to compile with some tweaks •  Results –  Any expressions/statements –  Lambdas/local classes •  Use it for your language! –  hOps://github.com/abreslav/eval4j