Eval4j @ JVMLS 2014

Preview:

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

Recommended