Upload
andrey-breslav
View
221
Download
0
Embed Size (px)
DESCRIPTION
eval4j: a JVM bytecode interpreter written in Java, used to implement "Evaluate Expression" functionality in debuggers for JVM Languages
Citation preview
eval4j
compiling expressions to be evaluated by the debugger
andrey.breslav@ .com
Stop at a breakpoint
Inspect memoryInspect call stacks
Evaluate given expression
Evaluate given expression
Working Horse: Bare JDI
• Access Variables• Access Fields• Call Methods
• No Evaluate Expression out-of-the-box JDI
How it’s done for Java
• IntelliJ has an intepreter for Java expressions– written from scratch– yet another definition of semantics– may disagree with the compiler’s semantics
• Well, IntelliJ’s not very intimate with javac
When you have your own compiler?
• Eclipse Java DT still has an interpreter• Scala IDE (Eclipse) — no Evaluate Expression• Ceylon IDE (Eclipse) — no Evaluate Expression
• There’s some room for improvement…
Reuse the Compiler (Take 1)
a + b.class
fileDebugeeprocess
compile
loadrun
IllegalAccessError
Eval4j: Bytecode Interpreter
• foo.x + 2– ALOAD 1– GETFIELD Foo.x : I– ICONST_2– IADD– INVOKESTATIC kotlin/io/IoPackage.println (I)V
• https://github.com/abreslav/eval4j• Re-uses ASM’s Interpreter
JDI
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 synthetic 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!– https://github.com/abreslav/eval4j