SlideShare uma empresa Scribd logo
1 de 139
@MSkarsaune
Martin Skarsaune
Java Developer and Co-Owner
A peek into the OpenJDK compiler :
goto java;
高
馬
丁
@MSkarsaune
GOTO Statements in Java!
@MSkarsaune
GOTO Statement – Objective
• Syntax
goto identifier;
• Runtime
• Program control moves to target statement
• Other Semantics
• Target (statement label) must be defined in same
scope, compilation error if not
• Potential circular gotos should give compilation
warning.
@MSkarsaune
GOTO Statement – Means
• OpenJDK
• Open source Java implementation
• Javac is implemented in plain Java 
• Modify compiler to support GOTO
@MSkarsaune
public class GotoSuccess {
public static void main(String[] args) {
one: System.out.print("goto ");
two: System.out.print(”J");
goto four;
three: System.out.print(”2017");
goto five;
four: System.out.print(”Fokus ");
goto three;
five: System.out.print("!");
}
}
Success Case
@MSkarsaune
GOTO
AHEAD
Dijkstra 1968:
programmerquality =100 1-
gotos
LoC
æ
è
ç
ö
ø
÷
@MSkarsaune
What is a Compiler?
Compiler
@MSkarsaune
What is a Compiler?
front
end
back
end
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
processAnnotations(enterTrees(…
parseFiles(…))),…)
…
generate(desugar(flow(attribute(…))))
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
processAnnotations(enterTrees(…
parseFiles(…))),…)
…
generate(desugar(flow(attribute(…))))
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
• Syntax: goto identifier;
• First convert character stream to token stream
(Scanner.java)
GOTO IDENTIFIER SEMI
[g][o][t][o][ ][f][o][u][r][;]
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
• goto is already a reserved word in Java!
• Lucky for us, goto is therefore defined as a
TokenKind.
• Tokens.java:141: GOTO(“goto”)
• The scanner therefore works out of the box!
@MSkarsaune
...
import com.sun.tools.javac.parser.Scanner;
...
Parse Enter Process Attribute Flow Desugar Generate
final Scanner scanner=factory.newScanner(”goto identifier;”, false);
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
final Scanner scanner=factory.newScanner(”goto identifier;”, false);
scanner.nextToken();
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
final Scanner scanner=factory.newScanner(”goto identifier;”, false);
scanner.nextToken();
assertThat(”First token is GOTO”, scanner.token().kind, is(GOTO));
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
final Scanner scanner=factory.newScanner(”goto identifier;”, false);
scanner.nextToken();
assertThat(”First token is GOTO”, scanner.token().kind, is(GOTO));
scanner.nextToken();
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
final Scanner scanner=factory.newScanner(”goto identifier;”, false);
scanner.nextToken();
assertThat(”First token is GOTO”, scanner.token().kind, is(GOTO));
scanner.nextToken();
assertThat("Second token is IDENTIFIER", scanner.token().kind,
is(IDENTIFIER));
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
final Scanner scanner=factory.newScanner(”goto identifier;”, false);
scanner.nextToken();
assertThat(”First token is GOTO”, scanner.token().kind, is(GOTO));
scanner.nextToken();
assertThat("Second token is IDENTIFIER", scanner.token().kind,
is(IDENTIFIER));
scanner.nextToken();
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
final Scanner scanner=factory.newScanner(”goto identifier;”, false);
scanner.nextToken();
assertThat(”First token is GOTO”, scanner.token().kind, is(GOTO));
scanner.nextToken();
assertThat("Second token is IDENTIFIER", scanner.token().kind,
is(IDENTIFIER));
scanner.nextToken();
assertThat("Third token is SEMI", scanner.token().kind, is(SEMI));
@MSkarsaune
visitClassDef(..)
visitMethodDef(..
)
visitIf(..)
Abstract Syntax Tree
[g][o][t][o][ ][f][o][u][r][;]
Wikipedia: “the visitor design pattern is a way of
separating an algorithm from an object
structure on which it operates”
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
Class Interface
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
Interface based visitors
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
Class based visitors
public void visitGoto(JCGoto tree) {
try {
print("goto " + tree.label + ";");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitGoto(JCGoto tree) {
//TODO implement
}
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
public static class JCLabeledStatement extends JCStatement
implements LabeledStatementTree {
…
public GotoResolver handler;
…
}
public class GotoResolver {
Map<GotoTree, Name> gotos;
Map<Name, LabeledStatementTree> targets;
List<StatementTree> statementsInSequence;
...
}
Helper object
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
JavacParser.parseStatement()
case GOTO: {
nextToken();
Name label = ident();
JCGoto t = to(F.at(pos).Goto(label, getGotoResolver());
accept(SEMI);
return t;
}
TreeMaker.java:
public JCGoto Goto(Name label, GotoResolver resolver) {
JCGoto tree = new JCGoto(label, resolver);
tree.pos = pos;
return tree;
}
@MSkarsaune
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
processAnnotations(enterTrees(…
parseFiles(…))),…)
…
generate(desugar(flow(attribute(…))))
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
processAnnotations(enterTrees(…
parseFiles(…))),…)
…
generate(desugar(flow(attribute(…))))
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
• Basic sanity testing of
compilation unit:
• File name and folder location
• Duplicate class names
• Corrections
• Add default constructor if no
constructors are declared
@MSkarsaune
Default Constructor
public class SimpleClass {
}
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
Default Constructor
public class SimpleClass {
public SimpleClass() {
super();
}
}
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
processAnnotations(enterTrees(…
parseFiles(…))),…)
…
generate(desugar(flow(attribute(…))))
@MSkarsaune
processAnnotations(enterTrees(…
parseFiles(…))),…)
…
generate(desugar(flow(attribute(…))))
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
• Process Annitations
• Annotation processing API
• Part of ordinary javac process since Java
1.6
• Plugin API (see javac documentation)
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
• Output controlled by command line
switches
@
- proc:only – only process annotations, do not compile
- proc:none – do not process annotations
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
processAnnotations(enterTrees(…
parseFiles(…))),…)
…
generate(desugar(flow(attribute(…))))
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
processAnnotations(enterTrees(…
parseFiles(…))),…)
…
generate(desugar(flow(attribute(…))))
@MSkarsaune
• Attribution
• Semantic checks
–Types
–References
• Corrections
–Add required calls to super constructor
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
Ensure target label exists in current scope
public class GotoMissingLabel {
public static void main(String[] args) {
one: System.out.print("goto ");
two: System.out.print(”Java");
goto six;
three: System.out.print(”2016");
goto five;
four: System.out.print(”One ");
goto three;
five: System.out.print("!");
}
}
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
Attr.java:
@Override
public void visitGoto(JCGoto that) {
that.findTarget();
if(that.target==null)
log.error(that.pos(), "undef.label", that.label);
result = null;
}
class JCGoto:
…
public void findTarget() {
this.target = (JCLabeledStatement)this.handler.findTarget(this);
}
@MSkarsaune
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
processAnnotations(enterTrees(…
parseFiles(…))),…)
…
generate(desugar(flow(attribute(…))))
@MSkarsaune
processAnnotations(enterTrees(…
parseFiles(…))),…)
…
generate(desugar(flow(attribute(…))))
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
Flow analysis
• Detect unreachable code
• Verify assignments
• Ensure proper method return
• Verify (effectively) final
• Check exception flow
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
Detect circular gotos
public class GotoCircularWarning {
public static void main(String[] args) {
one: System.out.print("goto ");
two: System.out.print(”Java");
goto four;
three: System.out.print(”2016");
goto five;
four: System.out.print(”One ");
goto three;
five: System.out.println("!");
goto one;//forms infinite loop
}
}
@MSkarsaune
Flow.FlowAnalyzer class:
compiler.properties:
@Override
public void visitGoto(JCGoto tree) {
if (tree.handler.detectCircularGotoPosition(tree))
log.warning(tree.pos, "circular.goto");
}
...
compiler.warn.circular.goto=circular goto
...
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
@MSkarsaune
processAnnotations(enterTrees(…
parseFiles(…))),…)
…
generate(desugar(flow(attribute(…))))
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
processAnnotations(enterTrees(…
parseFiles(…))),…)
…
generate(desugar(flow(attribute(…))))
@MSkarsaune
Erase generic types
public class Bridge implements Comparator {
}
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lowerpublic interface Comparator<T> {
int compare(T o1, T o1);
}or<T> {
@MSkarsaune
Erase generic types
public class Bridge implements Comparator<Integer> {
public int compare(Integer first, Integer second) {
return first - second;
}
}
TransTypes Unlambda Lower
Parse Enter Process Attribute Flow Desugar Generate
public interface Comparator<T> {
int compare(T o1, T o1);
} or<T> {
@MSkarsaune
Erasure - Runtime
public class Bridge implements Comparator {
public int compare(Integer first, Integer second) {
return first - second;
}
}
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
@MSkarsaune
Erasure - Bridge
public class Bridge implements Comparator {
public int compare(Integer first, Integer second) {
return first - second;
}
/*synthetic*/
public int compare(Object first, Object second) {
return this.compare((Integer)first, (Integer)second);
}
}
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
Extract inner class
public class Outer {
private void foo() { }
public Runnable fooRunner() {
return new Runnable() {
public void run() {
foo();
}
};
}
}
@MSkarsaune
Extract inner class
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
public class Outer {
private void foo() { }
public Runnable fooRunner() {
return new Runnable() {
public void run() {
foo();
}
};
}
}
@MSkarsaune
Extract inner class
public class Outer {
private void foo() { }
public Runnable fooRunner() {
return new Outer$1(this);
}
}
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
class Outer$1 implements Runnable {
final Outer this$0;
Outer$1(final Outer this$0) {
this.this$0 = this$0;
super();
}
public void run() {
this$0.foo();
}
}
@MSkarsaune
Extract inner class
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
public class Outer {
private void foo() { }
public Runnable fooRunner() {
return new Outer$1(this);
}
}
class Outer$1 implements Runnable {
final Outer this$0;
Outer$1(final Outer this$0) {
this.this$0 = this$0;
super();
}
public void run() {
this$0.foo();
}
}
@MSkarsaune
TransTypes Unlambda Lower
Parse Enter Process Attribute Flow Desugar Generate
Extract inner class
public class Outer {
private void foo() { }
public Runnable fooRunner() {
return new Outer$1(this);
}
/*synthetic*/
static void access$000(
Outer x0) {
x0.foo();
}
}
class Outer$1 implements Runnable {
final Outer this$0;
Outer$1(final Outer this$0) {
this.this$0 = this$0;
super();
}
public void run() {
Outer.access$000(this$0);
}
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
Boxing
List<Integer> list =
Arrays.asList(1, 2);
for (Integer i : list) {
System.out.println(”Double: “ + i * 2);
}
@MSkarsaune
Boxing
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
List<Integer> list =
Arrays.asList(1, 2);
for (Integer i : list) {
System.out.println(”Double: “ + i * 2);
}
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
Boxing
List<Integer> list =
Arrays.asList(Integer.valueOf(1), Integer.valueOf(2));
for (Integer i : list) {
System.out.println(”Double: “ + i * 2);
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
Unboxing
List<Integer> list =
Arrays.asList(Integer.valueOf(1), Integer.valueOf(2));
for (Integer i : list) {
System.out.println(”Double: “ + i * 2);
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
Unboxing
List<Integer> list =
Arrays.asList(Integer.valueOf(1), Integer.valueOf(2));
for (Integer i : list) {
System.out.println(”Double: “ + i.intValue() * 2);
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
Varargs
List<Integer> list =
Arrays.asList(Integer.valueOf(1), Integer.valueOf(2));
for (Integer i : list) {
System.out.println(”Double: “ + i.intValue() * 2);
}
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
Varargs
List<Integer> list =
Arrays.asList(Integer.valueOf(1), Integer.valueOf(2));
for (Integer i : list) {
System.out.println(”Double: “ + i.intValue() * 2);
}
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
Varargs - runtime
List<Integer> list =
Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)});
for (Integer i : list) {
System.out.println(”Double: “ + i.intValue() * 2);
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
For each loop
List<Integer> list =
Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)});
for (Integer i : list) {
System.out.println(”Double: “ + i.intValue() * 2);
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
For each loop
List<Integer> list =
Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)});
for (Integer i : list) {
System.out.println(”Double: “ + i.intValue() * 2);
}
public interface Iterable<T> {
Iterator<T> iterator();
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
For each loop
List<Integer> list =
Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)});
for (;;) {
System.out.println(”Double: “ + i.intValue() * 2);
}
@MSkarsaune
TransTypes Unlambda Lower
Parse Enter Process Attribute Flow Desugar Generate
For each loop
List<Integer> list =
Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)});
for (Iterator i$ = list.iterator();;) {
Integer i
System.out.println(”Double: “ + i.intValue() * 2);
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
For each loop
List<Integer> list =
Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)});
for (Iterator i$ = list.iterator(); i$.hasNext();) {
Integer i
System.out.println(”Double: “ + i.intValue() * 2);
}
@MSkarsaune
TransTypes Unlambda Lower
Parse Enter Process Attribute Flow Desugar Generate
For each loop
List<Integer> list =
Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)});
for (Iterator i$ = list.iterator(); i$.hasNext();) {
Integer i = (Integer)i$.next();
System.out.println(”Double: “ + i.intValue() * 2);
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
Enums
public enum Status {
YES, NO, MAYBE
}
@MSkarsaune
TransTypes Unlambda Lower
Parse Enter Process Attribute Flow Desugar Generate
Enums - constructor
public enum Status {
YES, NO, MAYBE
private Status(String $enum$name, int $enum$ordinal) {
super($enum$name, $enum$ordinal);
}
}
public static final Status TRUE = new Status("TRUE", 0);
public static final Status FALSE = new Status("FALSE", 1);
public static final Status MAYBE = new Status("MAYBE", 2);
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
Enums - valueOf
public enum Status {
YES, NO, MAYBE
private Status(String $enum$name, int $enum$ordinal) {
super($enum$name, $enum$ordinal);
}
public static Status valueOf(String name) {
return (Status)Enum.valueOf(Status.class, name);
}
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
Enums - values
public enum Status {
YES, NO, MAYBE
private Status(String $enum$name, int $enum$ordinal) {
super($enum$name, $enum$ordinal);
}
public static Status valueOf(String name) {
return (Status)Enum.valueOf(Status.class, name);
}
private static final Status[] $VALUES = new Status[]{
Status.YES, Status.NO, Status.MAYBE};
public static Status[] values() {
return (Status[])$VALUES.clone();
}
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
Enum switch statement
public class SwitchStatus {
void switchStatus(Status status) {
switch (status) {
case MAYBE:
return;
default:
break;
}
}
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
Enum switch statement
public class SwitchStatus {
void switchStatus(Status status) {
switch (status) {
case MAYBE:
return;
default:
break;
}
}
}
@MSkarsaune
TransTypes Unlambda Lower
Parse Enter Process Attribute Flow Desugar Generate
Enum switch statement
public class SwitchStatus {
void switchStatus(Status status) {
switch (SwitchStatus$1.$SwitchMap$Status[(status).ordinal()]) {
case 1:
return;
default:
break;
}
}
}
class SwitchStatus$1 {
}
@MSkarsaune
TransTypes Unlambda Lower
Parse Enter Process Attribute Flow Desugar Generate
Enum switch statement
public class SwitchStatus {
void switchStatus(Status status) {
switch (SwitchStatus$1.$SwitchMap$Status[(status).ordinal()]) {
case 1:
return;
default:
break;
}
}
}
class SwitchStatus$1 {
static final int[] $SwitchMap$Status = new
int[Status.values().length];
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
Enum switch statement
public class SwitchStatus {
void switchStatus(Status status) {
switch (SwitchStatus$1.$SwitchMap$Status[(status).ordinal()]) {
case 1:
return;
default:
break;
}
}
}
class SwitchStatus$1 {
static final int[] $SwitchMap$Status = new
int[Status.values().length]; [0][0][0]
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
Enum switch statement
public class SwitchStatus {
void switchStatus(Status status) {
switch (SwitchStatus$1.$SwitchMap$Status[(status).ordinal()]) {
case 1:
return;
default:
break;
}
}
}
class SwitchStatus$1 {
static final int[] $SwitchMap$Status = new
int[Status.values().length]; [0][0][1]
static {
try {
SwitchStatus$1.$SwitchMap$Status[Status.MAYBE.ordinal()] = 1;
} catch (NoSuchFieldError ex) { }
}
}
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
processAnnotations(enterTrees(…
parseFiles(…))),…)
…
generate(desugar(flow(attribute(…))))
@MSkarsaune
processAnnotations(enterTrees(…
parseFiles(…))),…)
…
generate(desugar(flow(attribute(…))))
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
• Organize initializers
• String concatenation
• Generate bytecodes
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
• Organize <init> (Constructor)
public class InstanceInitialization {
String key="key";
String value;
public InstanceInitialization(String value) {
this.value = value;
}
}
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
• Organize <init> (Constructor)
public class InstanceInitialization {
String key="key";
String value;
public InstanceInitialization(String value) {
super();
this.value = value;
}
}
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
• Organize <init> (Constructor)
public class InstanceInitialization {
String key;
String value;
public InstanceInitialization(String value) {
super();
key = ”key”;
this.value = value;
}
}
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
• Organize <init> (Constructor)
public class InstanceInitialization {
String key;
String value;
public void <init> () {
super();
key = ”key”;
this.value = value;
}
}
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
• Organize <clinit> (static initialization)
public class StaticInitialization {
static String key="key";
static {
init();
}
}
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
• Organize <clinit> (static initialization)
public class StaticInitialization {
static String key;
static {
key="key";
init();
}
}
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
• Organize <clinit> (static initialization)
public class StaticInitialization {
static String key;
static void <clinit>() {
key="key";
init();
}
}
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
String concatenation
Source code “Generated code”
”string” + value
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
String concatenation
Source code “Generated code”
”string” + value new StringBuilder()
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
String concatenation
Source code “Generated code”
”string” + value new StringBuilder()
.append(”string”)
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
String concatenation
Source code “Generated code”
”string” + value new StringBuilder()
.append(”string”)
.append(value)
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
String concatenation
Source code “Generated code”
”string” + value new StringBuilder()
.append(”string”)
.append(value)
.toString()
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
• Goto generation
–Luckily for us there is a GOTO byte code
–goto <addr>
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
if (<test>)
{
<ifblock>
}
else
{
<elseblock>
}
<codeafter>
Source code Byte codeCI
9 ifeq
<elseblock>
goto
<stackmap>
22 <ifblock>
22
<stackmap>
29 <codeafter>
29
Java >= 1.6:
Stack map frames must be
embedded at target of jump
instruction
Code generator (Code.java)
marked as not alive.
Goto instruction added to list of
pending jumps (Chain.java)
Pending jumps processed
Normal GOTO usage
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
Source code Byte codeCI
…
label: <somecode>
…
goto label;
…
20
… goto 20
<stackmap>
<somecode>
Used by goto?
Must emit stackmap
Emit goto to label
and turn code
generation on again
GOTO scenario 1 : jump back
@MSkarsaune
Source code Byte codeCI
GOTO scenario 2 : jump forward
…
goto label;
…
label: <somecode>
…
…
29 <somecode>
goto
<stackmap>
Label position not yet known?
• emit goto
• add to list of pending gotos
• turn generation on again
29
Label used?
• emit stack frame
• patch pending
gotos
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
• Goto generation
–Gen.java , visitor for code generation
–Modify for LabelledStatement
–Add implementation for Goto
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
• Gen.java – Labelled Statement
public void visitLabelled(JCLabeledStatement tree) {
// if the label is used from gotos, have to emit stack map
if (tree.handler.isUsed(tree))
code.emitStackMap();
…
}
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
• Gen.java – Goto
public void visitGoto(JCGoto tree) {
tree.handler.addBranch(new Chain(code.emitJump(goto_), null,
code.state.dup()), tree.target);
//normally goto marks code as not alive, turn generation on
code.entryPoint();
}
Target position known?
• Yes – patch immediately
• No – add to list of pending gotos
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
@MSkarsaune
@MSkarsaune
@MSkarsaune
• Lambda implementation in Java 8
–Language change
–Compilation
–Runtime support
• Many interesting design considerations
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
@MSkarsaune
Simple Example
public Comparator<String> lambdaExample() {
return (String a, String b) -> a.compareTo(b);
}
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
@MSkarsaune
LambdaToMethod.java
public Comparator<String> lambdaExample() {
return (String a, String b) -> a.compareTo(b);
}
/*synthetic*/
private static int
lambda$lambdaExample$0(
,
) {
return ;
}
final String a
final String b
a.compareTo(b)
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
@MSkarsaune
Runtime
public Comparator<String> lambdaExample() {
return <invokedynamic>LambdaMetafactory.metafactory(
}
/*synthetic*/
private static int
lambda$lambdaExample$0(
final String a,
final String b) {
return a.compareTo(b);
}
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
Lookup(LambdaExample), /*caller*/
"compare",
()Comparator, /*MethodType*/
(Object,Object)int, /*MethodType*/
lambda$lambdaexample$0,/*MethodHandle*/
(String,String)int); /*MethodType*/
final class LambdaExample$$Lambda$1/1834188994
implements Comparator {
private LambdaExample$$Lambda$1/1834188994()
public int compare(Object,Object)
}
public interface Comparator {/*erased*/
int compare(Object o1, Object o2);
}
@MSkarsaune
Runtime implementation
LambdaMetaFactory
• metaFactory(…)
• altMetaFactory(…)
InnerClassLambdaMetafactory
ASM
Lambda Class
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
@MSkarsaune
Serialization
Lambda
Instance
Serialize
Serialized
Lambda
Deserialize
Lambda
Meta
Factory
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
@MSkarsaune
• Possible to back port ?
–Capture generated class ?
–Compile time generation of inner class!
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
@MSkarsaune
Step 1: Source.java
public boolean allowLambda() {
return compareTo( ) >= 0;
}
JDK1_8JDK1_
5
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
@MSkarsaune
Step 2: Special handling
boolean mustBackportLambda() {
return this.target.compareTo(Target.JDK1_8) < 0;
}
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
@MSkarsaune
Step 3: Call backport
if(!this.attr.mustBackportLambda()) {
result = makeMetafactoryIndyCall(...);
}
else
{
result = new LambdaBackPorter(...).implementLambdaClass(...);
}
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
@MSkarsaune
Example implementation
private static final class Lambda$$2 implements Comparator<String> {
Lambda$$2 {
super();
}
public int compare(String arg0, String arg1) {
return LambdaExample.lambda$lambdaExample$0(arg0, arg1);
}
public int compare(Object o1, Object o2) {
return this.compare((String)o1, (String)o2);
}
}
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
@MSkarsaune
Example invoking
public Comparator<String> lambdaExample() {
}
return LambdaMetafactory.metafactory(...);return new Lambda$$2();
Parse Enter Process Attribute Flow Desugar Generate
TransTypes Unlambda Lower
@MSkarsaune
@MSkarsaune
@MSkarsaune
@MSkarsaune
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
• <invokedynamic> “playground”
1. @InvokeIndy annotation on method with
reference to boostrap method
2. Annotation processor that validates
reference
3. Compiler plugin that replaces method
invocation with invokedynamic
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
@IndyMethod
public class SomeService {
//must refer to a valid public static method
//with certain characteristics
@IndyMethod(
implementation="no.kantega.jvm.indy.example.SomeProvider",
method= "dummyMethod")
public static void doStuff() {
throw new UnsupportedOperationException("...");
}
}
@MSkarsaune
no.kantega.jvm.indy.compiler.plugin.IndyAnnotationChecker
Hooking in the processor:
META-INF/services/javax.annotation.processing.Processor:
Parse Enter Process Attribute Flow Desugar Generate
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
Annotation processor: setup, compliance + mapping
@SupportedAnnotationTypes("no....IndyMethod")
@SupportedSourceVersion(SourceVersion.RELEASE_8)//Java version
public class IndyAnnotationChecker extends AbstractProcessor {
//...
public boolean process(Set<...> annotations, RoundEnvironment roundEnv) {
for (TypeElement annotation : annotations) {
for (Element element : roundEnv.getElementsAnnotatedWith(annotation)) {
//...raise error if earlier than Java 7 or missing plugin
IndyMethod indyMethodRef = element.getAnnotation(IndyMethod.class);
if (indyMethodRef != null) {
//...check existance of type and compliance of method ...
processingEnv.getMessager().printMessage(Kind.ERROR,"...", element);
}
}
//...
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
...
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- Disable annotation processing for ourselves. -->
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
</plugins>
</build>
...
Disable annotation processing in the project that
implements the plugin (!): pom.xml :
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
• Compiler plugin
–Hook straight into the compilation process
–Respond to events from compilation process
–Make changes to AST
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
no.kantega.jvm.indy.compiler.plugin.IndyPlugin
Hooking in the plugin:
META-INF/services/com.sun.source.util.Plugin:
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
public class IndyPlugin implements Plugin {
public String getName() {
return "IndyPlugin";
}
public void init(JavacTask paramJavacTask,
String... paramArrayOfString) {
paramJavacTask.addTaskListener(
new GenerateInvokeDynamicHandler());
}
}
Typical plugin definition:
• Unique name
• Delegate to task listener(s)
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
public class GenerateInvokeDynamicHandler implements TaskListener {
public void started(TaskEvent start) {
if(start.getKind() == Kind.GENERATE) {
for (Tree tree : start.getCompilationUnit().getTypeDecls()) {
tree.accept(new IndyMethodInvocationReplacer(), tree);
}
}
}
Task listener:
• Receive callback, check stage
• Insert visitor to process ASTs
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
public class IndyMethodInvocationReplacer extends TreeScanner {
public Object visitMethodInvocation(MethodInvocationTree node, Tree p) {
{//...various checks on the method call
//...see if annotation processor has created mapping for it
MethodSymbol replacementMethod = IndyMethodMappings.getInstance().
mappingFor((MethodSymbol) identifier.sym);
if(replacementMethod!= null) {//insert reference to bootstrap
identifier.sym=new Symbol.DynamicMethodSymbol(...);
}
}
}
}
return super.visitMethodInvocation(node, p);
}
}
Visitor:
• Make modifications
@MSkarsaune
Parse Enter Process Attribute Flow Desugar Generate
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<arg>-Xplugin:IndyPlugin</arg>
</compilerArgs>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
Users:
• Enable plugin in compilation
@MSkarsaune
@MSkarsaune
Wrap Up
• The Java compiler is written in pure Java
• Compilation is done in phases
• Programming language advances (syntactic sugar)
require good compiler support
• Lambdas are compiled in a forward compatible manner
• Annotation processors and compiler plugins may be
used to tailor the compilation process to specific needs
@MSkarsaune
Resources
• OpenJDK
• Source: http://hg.openjdk.java.net/
• Compiler hacking tutorial
• http://www.ahristov.com/tutorial/java-compiler.html
• Sample code:
• https://github.com/skarsaune/goto
• https://github.com/skarsaune/indy-plugin
• Slide pack:
• http://www.slideshare.net/MartinSkarsaune
• 60 minute video (Devoxx) :
• https://youtu.be/gGTDQq6ZjIk
@MSkarsaune
Questions or
Comments?Martin Skarsaune
Java Developer and Co-Owner
@MSkarsaune
Thank You for
Your Time!Martin Skarsaune
Java Developer and Co-Owner

Mais conteúdo relacionado

Mais procurados

An Experiment with Checking the glibc Library
An Experiment with Checking the glibc LibraryAn Experiment with Checking the glibc Library
An Experiment with Checking the glibc LibraryAndrey Karpov
 
Demystifying dependency Injection: Dagger and Toothpick
Demystifying dependency Injection: Dagger and ToothpickDemystifying dependency Injection: Dagger and Toothpick
Demystifying dependency Injection: Dagger and ToothpickDanny Preussler
 
Session #4: Treating Databases as First-Class Citizens in Development
Session #4: Treating Databases as First-Class Citizens in DevelopmentSession #4: Treating Databases as First-Class Citizens in Development
Session #4: Treating Databases as First-Class Citizens in DevelopmentSteve Lange
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxDavid Rodenas
 
Tk2323 lecture 9 api json
Tk2323 lecture 9   api jsonTk2323 lecture 9   api json
Tk2323 lecture 9 api jsonMengChun Lam
 
JavaScript Proven Practises
JavaScript Proven PractisesJavaScript Proven Practises
JavaScript Proven PractisesRobert MacLean
 
Tomasz Polanski - Automated mobile testing 2016 - Testing: why, when, how
Tomasz Polanski - Automated mobile testing 2016 - Testing: why, when, howTomasz Polanski - Automated mobile testing 2016 - Testing: why, when, how
Tomasz Polanski - Automated mobile testing 2016 - Testing: why, when, howTomasz Polanski
 
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTR
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTRT3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTR
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTRDavid Gómez García
 
GeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleGeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleAnton Arhipov
 
Ip project work test your knowledge
Ip project work test your knowledgeIp project work test your knowledge
Ip project work test your knowledgeKïShørê Choudhary
 
Слава Бобик «NancyFx для самых маленьких»
Слава Бобик «NancyFx для самых маленьких»Слава Бобик «NancyFx для самых маленьких»
Слава Бобик «NancyFx для самых маленьких»SpbDotNet Community
 
Advanced Java Practical File
Advanced Java Practical FileAdvanced Java Practical File
Advanced Java Practical FileSoumya Behera
 
201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programingwahyuseptiansyah
 
Webinar: Simplifying Persistence for Java and MongoDB
Webinar: Simplifying Persistence for Java and MongoDBWebinar: Simplifying Persistence for Java and MongoDB
Webinar: Simplifying Persistence for Java and MongoDBMongoDB
 

Mais procurados (19)

Migrating to JUnit 5
Migrating to JUnit 5Migrating to JUnit 5
Migrating to JUnit 5
 
An Experiment with Checking the glibc Library
An Experiment with Checking the glibc LibraryAn Experiment with Checking the glibc Library
An Experiment with Checking the glibc Library
 
Demystifying dependency Injection: Dagger and Toothpick
Demystifying dependency Injection: Dagger and ToothpickDemystifying dependency Injection: Dagger and Toothpick
Demystifying dependency Injection: Dagger and Toothpick
 
Session #4: Treating Databases as First-Class Citizens in Development
Session #4: Treating Databases as First-Class Citizens in DevelopmentSession #4: Treating Databases as First-Class Citizens in Development
Session #4: Treating Databases as First-Class Citizens in Development
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicox
 
Tk2323 lecture 9 api json
Tk2323 lecture 9   api jsonTk2323 lecture 9   api json
Tk2323 lecture 9 api json
 
Unit testing concurrent code
Unit testing concurrent codeUnit testing concurrent code
Unit testing concurrent code
 
JavaScript Proven Practises
JavaScript Proven PractisesJavaScript Proven Practises
JavaScript Proven Practises
 
Easy Button
Easy ButtonEasy Button
Easy Button
 
04 Data Access
04 Data Access04 Data Access
04 Data Access
 
Tomasz Polanski - Automated mobile testing 2016 - Testing: why, when, how
Tomasz Polanski - Automated mobile testing 2016 - Testing: why, when, howTomasz Polanski - Automated mobile testing 2016 - Testing: why, when, how
Tomasz Polanski - Automated mobile testing 2016 - Testing: why, when, how
 
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTR
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTRT3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTR
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTR
 
GeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleGeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassle
 
Ip project work test your knowledge
Ip project work test your knowledgeIp project work test your knowledge
Ip project work test your knowledge
 
Слава Бобик «NancyFx для самых маленьких»
Слава Бобик «NancyFx для самых маленьких»Слава Бобик «NancyFx для самых маленьких»
Слава Бобик «NancyFx для самых маленьких»
 
Advanced Java Practical File
Advanced Java Practical FileAdvanced Java Practical File
Advanced Java Practical File
 
201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing
 
Specs2
Specs2Specs2
Specs2
 
Webinar: Simplifying Persistence for Java and MongoDB
Webinar: Simplifying Persistence for Java and MongoDBWebinar: Simplifying Persistence for Java and MongoDB
Webinar: Simplifying Persistence for Java and MongoDB
 

Semelhante a goto java; (Jfokus)

Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksMongoDB
 
Deep Dive into Zone.JS
Deep Dive into Zone.JSDeep Dive into Zone.JS
Deep Dive into Zone.JSIlia Idakiev
 
Tame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapperTame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapperGiordano Scalzo
 
V8 javascript engine for フロントエンドデベロッパー
V8 javascript engine for フロントエンドデベロッパーV8 javascript engine for フロントエンドデベロッパー
V8 javascript engine for フロントエンドデベロッパーTaketoshi 青野健利
 
Programming with Python and PostgreSQL
Programming with Python and PostgreSQLProgramming with Python and PostgreSQL
Programming with Python and PostgreSQLPeter Eisentraut
 
Introduction to Scalding and Monoids
Introduction to Scalding and MonoidsIntroduction to Scalding and Monoids
Introduction to Scalding and MonoidsHugo Gävert
 
Functional patterns and techniques in C#
Functional patterns and techniques in C#Functional patterns and techniques in C#
Functional patterns and techniques in C#Péter Takács
 
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGeneBang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGeneDroidConTLV
 
MegaScriptSample - Released x-x-15
MegaScriptSample - Released x-x-15MegaScriptSample - Released x-x-15
MegaScriptSample - Released x-x-15Bob Powers
 
Introduction To Groovy 2005
Introduction To Groovy 2005Introduction To Groovy 2005
Introduction To Groovy 2005Tugdual Grall
 
Informatica_MDM_User_Exits.ppt
Informatica_MDM_User_Exits.pptInformatica_MDM_User_Exits.ppt
Informatica_MDM_User_Exits.pptDurganandYedlapati
 
Transaction Management Tool
Transaction Management ToolTransaction Management Tool
Transaction Management ToolPeeyush Ranjan
 
Java Annotation Processing: A Beginner Walkthrough
Java Annotation Processing: A Beginner WalkthroughJava Annotation Processing: A Beginner Walkthrough
Java Annotation Processing: A Beginner WalkthroughMahfuz Islam Bhuiyan
 
Introduction to Elasticsearch
Introduction to ElasticsearchIntroduction to Elasticsearch
Introduction to ElasticsearchSperasoft
 
Test First Refresh Second: Test-Driven Development in Grails
Test First Refresh Second: Test-Driven Development in GrailsTest First Refresh Second: Test-Driven Development in Grails
Test First Refresh Second: Test-Driven Development in GrailsTim Berglund
 
Cascading Through Hadoop for the Boulder JUG
Cascading Through Hadoop for the Boulder JUGCascading Through Hadoop for the Boulder JUG
Cascading Through Hadoop for the Boulder JUGMatthew McCullough
 

Semelhante a goto java; (Jfokus) (20)

Goto devoxx
Goto devoxxGoto devoxx
Goto devoxx
 
Clean coding-practices
Clean coding-practicesClean coding-practices
Clean coding-practices
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
 
Deep Dive into Zone.JS
Deep Dive into Zone.JSDeep Dive into Zone.JS
Deep Dive into Zone.JS
 
Metaprogramming
MetaprogrammingMetaprogramming
Metaprogramming
 
Tame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapperTame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapper
 
V8 javascript engine for フロントエンドデベロッパー
V8 javascript engine for フロントエンドデベロッパーV8 javascript engine for フロントエンドデベロッパー
V8 javascript engine for フロントエンドデベロッパー
 
Programming with Python and PostgreSQL
Programming with Python and PostgreSQLProgramming with Python and PostgreSQL
Programming with Python and PostgreSQL
 
Introduction to Scalding and Monoids
Introduction to Scalding and MonoidsIntroduction to Scalding and Monoids
Introduction to Scalding and Monoids
 
Functional patterns and techniques in C#
Functional patterns and techniques in C#Functional patterns and techniques in C#
Functional patterns and techniques in C#
 
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGeneBang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
 
MegaScriptSample - Released x-x-15
MegaScriptSample - Released x-x-15MegaScriptSample - Released x-x-15
MegaScriptSample - Released x-x-15
 
Introduction To Groovy 2005
Introduction To Groovy 2005Introduction To Groovy 2005
Introduction To Groovy 2005
 
Informatica_MDM_User_Exits.ppt
Informatica_MDM_User_Exits.pptInformatica_MDM_User_Exits.ppt
Informatica_MDM_User_Exits.ppt
 
Transaction Management Tool
Transaction Management ToolTransaction Management Tool
Transaction Management Tool
 
Java Annotation Processing: A Beginner Walkthrough
Java Annotation Processing: A Beginner WalkthroughJava Annotation Processing: A Beginner Walkthrough
Java Annotation Processing: A Beginner Walkthrough
 
Introduction to Elasticsearch
Introduction to ElasticsearchIntroduction to Elasticsearch
Introduction to Elasticsearch
 
Struts2 notes
Struts2 notesStruts2 notes
Struts2 notes
 
Test First Refresh Second: Test-Driven Development in Grails
Test First Refresh Second: Test-Driven Development in GrailsTest First Refresh Second: Test-Driven Development in Grails
Test First Refresh Second: Test-Driven Development in Grails
 
Cascading Through Hadoop for the Boulder JUG
Cascading Through Hadoop for the Boulder JUGCascading Through Hadoop for the Boulder JUG
Cascading Through Hadoop for the Boulder JUG
 

Mais de Martin (高馬丁) Skarsaune (10)

jmc-devoxx.pptx
jmc-devoxx.pptxjmc-devoxx.pptx
jmc-devoxx.pptx
 
Flight recordings and mission control through thick clouds
Flight recordings and mission control through thick cloudsFlight recordings and mission control through thick clouds
Flight recordings and mission control through thick clouds
 
Cloud Collaboration with Eclipse Che
Cloud Collaboration with Eclipse CheCloud Collaboration with Eclipse Che
Cloud Collaboration with Eclipse Che
 
CodeOne Java Debugging Tips
CodeOne Java Debugging TipsCodeOne Java Debugging Tips
CodeOne Java Debugging Tips
 
Java Debugging Tips @oredev
Java Debugging Tips @oredevJava Debugging Tips @oredev
Java Debugging Tips @oredev
 
Tricks
TricksTricks
Tricks
 
Small Lambda Talk @Booster2015
Small Lambda Talk @Booster2015Small Lambda Talk @Booster2015
Small Lambda Talk @Booster2015
 
Small lambda talk
Small lambda talkSmall lambda talk
Small lambda talk
 
Bring your calculations to Scala!
Bring your calculations to Scala!Bring your calculations to Scala!
Bring your calculations to Scala!
 
JavaZone 2014 - Iteration 2.0: Stream
JavaZone 2014 - Iteration 2.0: StreamJavaZone 2014 - Iteration 2.0: Stream
JavaZone 2014 - Iteration 2.0: Stream
 

Último

Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf31events.com
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalLionel Briand
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsSafe Software
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Developmentvyaparkranti
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Mater
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsChristian Birchler
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringHironori Washizaki
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfMarharyta Nedzelska
 
Post Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on IdentityPost Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on Identityteam-WIBU
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 

Último (20)

Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive Goal
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data Streams
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Development
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their Engineering
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdf
 
Post Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on IdentityPost Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on Identity
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 

goto java; (Jfokus)

  • 1. @MSkarsaune Martin Skarsaune Java Developer and Co-Owner A peek into the OpenJDK compiler : goto java; 高 馬 丁
  • 3. @MSkarsaune GOTO Statement – Objective • Syntax goto identifier; • Runtime • Program control moves to target statement • Other Semantics • Target (statement label) must be defined in same scope, compilation error if not • Potential circular gotos should give compilation warning.
  • 4. @MSkarsaune GOTO Statement – Means • OpenJDK • Open source Java implementation • Javac is implemented in plain Java  • Modify compiler to support GOTO
  • 5. @MSkarsaune public class GotoSuccess { public static void main(String[] args) { one: System.out.print("goto "); two: System.out.print(”J"); goto four; three: System.out.print(”2017"); goto five; four: System.out.print(”Fokus "); goto three; five: System.out.print("!"); } } Success Case
  • 7. @MSkarsaune What is a Compiler? Compiler
  • 8. @MSkarsaune What is a Compiler? front end back end
  • 9. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate processAnnotations(enterTrees(… parseFiles(…))),…) … generate(desugar(flow(attribute(…))))
  • 10. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate processAnnotations(enterTrees(… parseFiles(…))),…) … generate(desugar(flow(attribute(…))))
  • 11. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate • Syntax: goto identifier; • First convert character stream to token stream (Scanner.java) GOTO IDENTIFIER SEMI [g][o][t][o][ ][f][o][u][r][;]
  • 12. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate • goto is already a reserved word in Java! • Lucky for us, goto is therefore defined as a TokenKind. • Tokens.java:141: GOTO(“goto”) • The scanner therefore works out of the box!
  • 13. @MSkarsaune ... import com.sun.tools.javac.parser.Scanner; ... Parse Enter Process Attribute Flow Desugar Generate final Scanner scanner=factory.newScanner(”goto identifier;”, false);
  • 14. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate final Scanner scanner=factory.newScanner(”goto identifier;”, false); scanner.nextToken();
  • 15. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate final Scanner scanner=factory.newScanner(”goto identifier;”, false); scanner.nextToken(); assertThat(”First token is GOTO”, scanner.token().kind, is(GOTO));
  • 16. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate final Scanner scanner=factory.newScanner(”goto identifier;”, false); scanner.nextToken(); assertThat(”First token is GOTO”, scanner.token().kind, is(GOTO)); scanner.nextToken();
  • 17. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate final Scanner scanner=factory.newScanner(”goto identifier;”, false); scanner.nextToken(); assertThat(”First token is GOTO”, scanner.token().kind, is(GOTO)); scanner.nextToken(); assertThat("Second token is IDENTIFIER", scanner.token().kind, is(IDENTIFIER));
  • 18. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate final Scanner scanner=factory.newScanner(”goto identifier;”, false); scanner.nextToken(); assertThat(”First token is GOTO”, scanner.token().kind, is(GOTO)); scanner.nextToken(); assertThat("Second token is IDENTIFIER", scanner.token().kind, is(IDENTIFIER)); scanner.nextToken();
  • 19. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate final Scanner scanner=factory.newScanner(”goto identifier;”, false); scanner.nextToken(); assertThat(”First token is GOTO”, scanner.token().kind, is(GOTO)); scanner.nextToken(); assertThat("Second token is IDENTIFIER", scanner.token().kind, is(IDENTIFIER)); scanner.nextToken(); assertThat("Third token is SEMI", scanner.token().kind, is(SEMI));
  • 20. @MSkarsaune visitClassDef(..) visitMethodDef(.. ) visitIf(..) Abstract Syntax Tree [g][o][t][o][ ][f][o][u][r][;] Wikipedia: “the visitor design pattern is a way of separating an algorithm from an object structure on which it operates” Parse Enter Process Attribute Flow Desugar Generate
  • 21. @MSkarsaune Class Interface Parse Enter Process Attribute Flow Desugar Generate
  • 22. @MSkarsaune Interface based visitors Parse Enter Process Attribute Flow Desugar Generate
  • 23. @MSkarsaune Class based visitors public void visitGoto(JCGoto tree) { try { print("goto " + tree.label + ";"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitGoto(JCGoto tree) { //TODO implement } Parse Enter Process Attribute Flow Desugar Generate
  • 24. @MSkarsaune public static class JCLabeledStatement extends JCStatement implements LabeledStatementTree { … public GotoResolver handler; … } public class GotoResolver { Map<GotoTree, Name> gotos; Map<Name, LabeledStatementTree> targets; List<StatementTree> statementsInSequence; ... } Helper object Parse Enter Process Attribute Flow Desugar Generate
  • 25. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate JavacParser.parseStatement() case GOTO: { nextToken(); Name label = ident(); JCGoto t = to(F.at(pos).Goto(label, getGotoResolver()); accept(SEMI); return t; } TreeMaker.java: public JCGoto Goto(Name label, GotoResolver resolver) { JCGoto tree = new JCGoto(label, resolver); tree.pos = pos; return tree; }
  • 27. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate processAnnotations(enterTrees(… parseFiles(…))),…) … generate(desugar(flow(attribute(…))))
  • 28. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate processAnnotations(enterTrees(… parseFiles(…))),…) … generate(desugar(flow(attribute(…))))
  • 29. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate • Basic sanity testing of compilation unit: • File name and folder location • Duplicate class names • Corrections • Add default constructor if no constructors are declared
  • 30. @MSkarsaune Default Constructor public class SimpleClass { } Parse Enter Process Attribute Flow Desugar Generate
  • 31. @MSkarsaune Default Constructor public class SimpleClass { public SimpleClass() { super(); } } Parse Enter Process Attribute Flow Desugar Generate
  • 32. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate processAnnotations(enterTrees(… parseFiles(…))),…) … generate(desugar(flow(attribute(…))))
  • 34. @MSkarsaune • Process Annitations • Annotation processing API • Part of ordinary javac process since Java 1.6 • Plugin API (see javac documentation) Parse Enter Process Attribute Flow Desugar Generate
  • 35. @MSkarsaune • Output controlled by command line switches @ - proc:only – only process annotations, do not compile - proc:none – do not process annotations Parse Enter Process Attribute Flow Desugar Generate
  • 36. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate processAnnotations(enterTrees(… parseFiles(…))),…) … generate(desugar(flow(attribute(…))))
  • 37. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate processAnnotations(enterTrees(… parseFiles(…))),…) … generate(desugar(flow(attribute(…))))
  • 38. @MSkarsaune • Attribution • Semantic checks –Types –References • Corrections –Add required calls to super constructor Parse Enter Process Attribute Flow Desugar Generate
  • 39. @MSkarsaune Ensure target label exists in current scope public class GotoMissingLabel { public static void main(String[] args) { one: System.out.print("goto "); two: System.out.print(”Java"); goto six; three: System.out.print(”2016"); goto five; four: System.out.print(”One "); goto three; five: System.out.print("!"); } } Parse Enter Process Attribute Flow Desugar Generate
  • 40. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate Attr.java: @Override public void visitGoto(JCGoto that) { that.findTarget(); if(that.target==null) log.error(that.pos(), "undef.label", that.label); result = null; } class JCGoto: … public void findTarget() { this.target = (JCLabeledStatement)this.handler.findTarget(this); }
  • 42. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate processAnnotations(enterTrees(… parseFiles(…))),…) … generate(desugar(flow(attribute(…))))
  • 44. @MSkarsaune Flow analysis • Detect unreachable code • Verify assignments • Ensure proper method return • Verify (effectively) final • Check exception flow Parse Enter Process Attribute Flow Desugar Generate
  • 45. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate Detect circular gotos public class GotoCircularWarning { public static void main(String[] args) { one: System.out.print("goto "); two: System.out.print(”Java"); goto four; three: System.out.print(”2016"); goto five; four: System.out.print(”One "); goto three; five: System.out.println("!"); goto one;//forms infinite loop } }
  • 46. @MSkarsaune Flow.FlowAnalyzer class: compiler.properties: @Override public void visitGoto(JCGoto tree) { if (tree.handler.detectCircularGotoPosition(tree)) log.warning(tree.pos, "circular.goto"); } ... compiler.warn.circular.goto=circular goto ... Parse Enter Process Attribute Flow Desugar Generate
  • 49. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate processAnnotations(enterTrees(… parseFiles(…))),…) … generate(desugar(flow(attribute(…))))
  • 50. @MSkarsaune Erase generic types public class Bridge implements Comparator { } Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lowerpublic interface Comparator<T> { int compare(T o1, T o1); }or<T> {
  • 51. @MSkarsaune Erase generic types public class Bridge implements Comparator<Integer> { public int compare(Integer first, Integer second) { return first - second; } } TransTypes Unlambda Lower Parse Enter Process Attribute Flow Desugar Generate public interface Comparator<T> { int compare(T o1, T o1); } or<T> {
  • 52. @MSkarsaune Erasure - Runtime public class Bridge implements Comparator { public int compare(Integer first, Integer second) { return first - second; } } Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower
  • 53. @MSkarsaune Erasure - Bridge public class Bridge implements Comparator { public int compare(Integer first, Integer second) { return first - second; } /*synthetic*/ public int compare(Object first, Object second) { return this.compare((Integer)first, (Integer)second); } } Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower
  • 54. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower Extract inner class public class Outer { private void foo() { } public Runnable fooRunner() { return new Runnable() { public void run() { foo(); } }; } }
  • 55. @MSkarsaune Extract inner class Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower public class Outer { private void foo() { } public Runnable fooRunner() { return new Runnable() { public void run() { foo(); } }; } }
  • 56. @MSkarsaune Extract inner class public class Outer { private void foo() { } public Runnable fooRunner() { return new Outer$1(this); } } Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower class Outer$1 implements Runnable { final Outer this$0; Outer$1(final Outer this$0) { this.this$0 = this$0; super(); } public void run() { this$0.foo(); } }
  • 57. @MSkarsaune Extract inner class Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower public class Outer { private void foo() { } public Runnable fooRunner() { return new Outer$1(this); } } class Outer$1 implements Runnable { final Outer this$0; Outer$1(final Outer this$0) { this.this$0 = this$0; super(); } public void run() { this$0.foo(); } }
  • 58. @MSkarsaune TransTypes Unlambda Lower Parse Enter Process Attribute Flow Desugar Generate Extract inner class public class Outer { private void foo() { } public Runnable fooRunner() { return new Outer$1(this); } /*synthetic*/ static void access$000( Outer x0) { x0.foo(); } } class Outer$1 implements Runnable { final Outer this$0; Outer$1(final Outer this$0) { this.this$0 = this$0; super(); } public void run() { Outer.access$000(this$0); } }
  • 59. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower Boxing List<Integer> list = Arrays.asList(1, 2); for (Integer i : list) { System.out.println(”Double: “ + i * 2); }
  • 60. @MSkarsaune Boxing Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower List<Integer> list = Arrays.asList(1, 2); for (Integer i : list) { System.out.println(”Double: “ + i * 2); } public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }
  • 61. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower Boxing List<Integer> list = Arrays.asList(Integer.valueOf(1), Integer.valueOf(2)); for (Integer i : list) { System.out.println(”Double: “ + i * 2); }
  • 62. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower Unboxing List<Integer> list = Arrays.asList(Integer.valueOf(1), Integer.valueOf(2)); for (Integer i : list) { System.out.println(”Double: “ + i * 2); }
  • 63. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower Unboxing List<Integer> list = Arrays.asList(Integer.valueOf(1), Integer.valueOf(2)); for (Integer i : list) { System.out.println(”Double: “ + i.intValue() * 2); }
  • 64. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower Varargs List<Integer> list = Arrays.asList(Integer.valueOf(1), Integer.valueOf(2)); for (Integer i : list) { System.out.println(”Double: “ + i.intValue() * 2); } public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }
  • 65. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower Varargs List<Integer> list = Arrays.asList(Integer.valueOf(1), Integer.valueOf(2)); for (Integer i : list) { System.out.println(”Double: “ + i.intValue() * 2); } public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }
  • 66. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower Varargs - runtime List<Integer> list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)}); for (Integer i : list) { System.out.println(”Double: “ + i.intValue() * 2); }
  • 67. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower For each loop List<Integer> list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)}); for (Integer i : list) { System.out.println(”Double: “ + i.intValue() * 2); }
  • 68. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower For each loop List<Integer> list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)}); for (Integer i : list) { System.out.println(”Double: “ + i.intValue() * 2); } public interface Iterable<T> { Iterator<T> iterator(); }
  • 69. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower For each loop List<Integer> list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)}); for (;;) { System.out.println(”Double: “ + i.intValue() * 2); }
  • 70. @MSkarsaune TransTypes Unlambda Lower Parse Enter Process Attribute Flow Desugar Generate For each loop List<Integer> list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)}); for (Iterator i$ = list.iterator();;) { Integer i System.out.println(”Double: “ + i.intValue() * 2); }
  • 71. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower For each loop List<Integer> list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)}); for (Iterator i$ = list.iterator(); i$.hasNext();) { Integer i System.out.println(”Double: “ + i.intValue() * 2); }
  • 72. @MSkarsaune TransTypes Unlambda Lower Parse Enter Process Attribute Flow Desugar Generate For each loop List<Integer> list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)}); for (Iterator i$ = list.iterator(); i$.hasNext();) { Integer i = (Integer)i$.next(); System.out.println(”Double: “ + i.intValue() * 2); }
  • 73. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower Enums public enum Status { YES, NO, MAYBE }
  • 74. @MSkarsaune TransTypes Unlambda Lower Parse Enter Process Attribute Flow Desugar Generate Enums - constructor public enum Status { YES, NO, MAYBE private Status(String $enum$name, int $enum$ordinal) { super($enum$name, $enum$ordinal); } } public static final Status TRUE = new Status("TRUE", 0); public static final Status FALSE = new Status("FALSE", 1); public static final Status MAYBE = new Status("MAYBE", 2);
  • 75. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower Enums - valueOf public enum Status { YES, NO, MAYBE private Status(String $enum$name, int $enum$ordinal) { super($enum$name, $enum$ordinal); } public static Status valueOf(String name) { return (Status)Enum.valueOf(Status.class, name); } }
  • 76. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower Enums - values public enum Status { YES, NO, MAYBE private Status(String $enum$name, int $enum$ordinal) { super($enum$name, $enum$ordinal); } public static Status valueOf(String name) { return (Status)Enum.valueOf(Status.class, name); } private static final Status[] $VALUES = new Status[]{ Status.YES, Status.NO, Status.MAYBE}; public static Status[] values() { return (Status[])$VALUES.clone(); } }
  • 77. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower Enum switch statement public class SwitchStatus { void switchStatus(Status status) { switch (status) { case MAYBE: return; default: break; } } }
  • 78. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower Enum switch statement public class SwitchStatus { void switchStatus(Status status) { switch (status) { case MAYBE: return; default: break; } } }
  • 79. @MSkarsaune TransTypes Unlambda Lower Parse Enter Process Attribute Flow Desugar Generate Enum switch statement public class SwitchStatus { void switchStatus(Status status) { switch (SwitchStatus$1.$SwitchMap$Status[(status).ordinal()]) { case 1: return; default: break; } } } class SwitchStatus$1 { }
  • 80. @MSkarsaune TransTypes Unlambda Lower Parse Enter Process Attribute Flow Desugar Generate Enum switch statement public class SwitchStatus { void switchStatus(Status status) { switch (SwitchStatus$1.$SwitchMap$Status[(status).ordinal()]) { case 1: return; default: break; } } } class SwitchStatus$1 { static final int[] $SwitchMap$Status = new int[Status.values().length]; }
  • 81. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower Enum switch statement public class SwitchStatus { void switchStatus(Status status) { switch (SwitchStatus$1.$SwitchMap$Status[(status).ordinal()]) { case 1: return; default: break; } } } class SwitchStatus$1 { static final int[] $SwitchMap$Status = new int[Status.values().length]; [0][0][0] }
  • 82. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower Enum switch statement public class SwitchStatus { void switchStatus(Status status) { switch (SwitchStatus$1.$SwitchMap$Status[(status).ordinal()]) { case 1: return; default: break; } } } class SwitchStatus$1 { static final int[] $SwitchMap$Status = new int[Status.values().length]; [0][0][1] static { try { SwitchStatus$1.$SwitchMap$Status[Status.MAYBE.ordinal()] = 1; } catch (NoSuchFieldError ex) { } } }
  • 83. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate processAnnotations(enterTrees(… parseFiles(…))),…) … generate(desugar(flow(attribute(…))))
  • 85. @MSkarsaune • Organize initializers • String concatenation • Generate bytecodes Parse Enter Process Attribute Flow Desugar Generate
  • 86. @MSkarsaune • Organize <init> (Constructor) public class InstanceInitialization { String key="key"; String value; public InstanceInitialization(String value) { this.value = value; } } Parse Enter Process Attribute Flow Desugar Generate
  • 87. @MSkarsaune • Organize <init> (Constructor) public class InstanceInitialization { String key="key"; String value; public InstanceInitialization(String value) { super(); this.value = value; } } Parse Enter Process Attribute Flow Desugar Generate
  • 88. @MSkarsaune • Organize <init> (Constructor) public class InstanceInitialization { String key; String value; public InstanceInitialization(String value) { super(); key = ”key”; this.value = value; } } Parse Enter Process Attribute Flow Desugar Generate
  • 89. @MSkarsaune • Organize <init> (Constructor) public class InstanceInitialization { String key; String value; public void <init> () { super(); key = ”key”; this.value = value; } } Parse Enter Process Attribute Flow Desugar Generate
  • 90. @MSkarsaune • Organize <clinit> (static initialization) public class StaticInitialization { static String key="key"; static { init(); } } Parse Enter Process Attribute Flow Desugar Generate
  • 91. @MSkarsaune • Organize <clinit> (static initialization) public class StaticInitialization { static String key; static { key="key"; init(); } } Parse Enter Process Attribute Flow Desugar Generate
  • 92. @MSkarsaune • Organize <clinit> (static initialization) public class StaticInitialization { static String key; static void <clinit>() { key="key"; init(); } } Parse Enter Process Attribute Flow Desugar Generate
  • 93. @MSkarsaune String concatenation Source code “Generated code” ”string” + value Parse Enter Process Attribute Flow Desugar Generate
  • 94. @MSkarsaune String concatenation Source code “Generated code” ”string” + value new StringBuilder() Parse Enter Process Attribute Flow Desugar Generate
  • 95. @MSkarsaune String concatenation Source code “Generated code” ”string” + value new StringBuilder() .append(”string”) Parse Enter Process Attribute Flow Desugar Generate
  • 96. @MSkarsaune String concatenation Source code “Generated code” ”string” + value new StringBuilder() .append(”string”) .append(value) Parse Enter Process Attribute Flow Desugar Generate
  • 97. @MSkarsaune String concatenation Source code “Generated code” ”string” + value new StringBuilder() .append(”string”) .append(value) .toString() Parse Enter Process Attribute Flow Desugar Generate
  • 98. @MSkarsaune • Goto generation –Luckily for us there is a GOTO byte code –goto <addr> Parse Enter Process Attribute Flow Desugar Generate
  • 99. @MSkarsaune if (<test>) { <ifblock> } else { <elseblock> } <codeafter> Source code Byte codeCI 9 ifeq <elseblock> goto <stackmap> 22 <ifblock> 22 <stackmap> 29 <codeafter> 29 Java >= 1.6: Stack map frames must be embedded at target of jump instruction Code generator (Code.java) marked as not alive. Goto instruction added to list of pending jumps (Chain.java) Pending jumps processed Normal GOTO usage Parse Enter Process Attribute Flow Desugar Generate
  • 100. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate Source code Byte codeCI … label: <somecode> … goto label; … 20 … goto 20 <stackmap> <somecode> Used by goto? Must emit stackmap Emit goto to label and turn code generation on again GOTO scenario 1 : jump back
  • 101. @MSkarsaune Source code Byte codeCI GOTO scenario 2 : jump forward … goto label; … label: <somecode> … … 29 <somecode> goto <stackmap> Label position not yet known? • emit goto • add to list of pending gotos • turn generation on again 29 Label used? • emit stack frame • patch pending gotos Parse Enter Process Attribute Flow Desugar Generate
  • 102. @MSkarsaune • Goto generation –Gen.java , visitor for code generation –Modify for LabelledStatement –Add implementation for Goto Parse Enter Process Attribute Flow Desugar Generate
  • 103. @MSkarsaune • Gen.java – Labelled Statement public void visitLabelled(JCLabeledStatement tree) { // if the label is used from gotos, have to emit stack map if (tree.handler.isUsed(tree)) code.emitStackMap(); … } Parse Enter Process Attribute Flow Desugar Generate
  • 104. @MSkarsaune • Gen.java – Goto public void visitGoto(JCGoto tree) { tree.handler.addBranch(new Chain(code.emitJump(goto_), null, code.state.dup()), tree.target); //normally goto marks code as not alive, turn generation on code.entryPoint(); } Target position known? • Yes – patch immediately • No – add to list of pending gotos Parse Enter Process Attribute Flow Desugar Generate
  • 108. @MSkarsaune • Lambda implementation in Java 8 –Language change –Compilation –Runtime support • Many interesting design considerations Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower
  • 109. @MSkarsaune Simple Example public Comparator<String> lambdaExample() { return (String a, String b) -> a.compareTo(b); } Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower
  • 110. @MSkarsaune LambdaToMethod.java public Comparator<String> lambdaExample() { return (String a, String b) -> a.compareTo(b); } /*synthetic*/ private static int lambda$lambdaExample$0( , ) { return ; } final String a final String b a.compareTo(b) Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower
  • 111. @MSkarsaune Runtime public Comparator<String> lambdaExample() { return <invokedynamic>LambdaMetafactory.metafactory( } /*synthetic*/ private static int lambda$lambdaExample$0( final String a, final String b) { return a.compareTo(b); } Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower Lookup(LambdaExample), /*caller*/ "compare", ()Comparator, /*MethodType*/ (Object,Object)int, /*MethodType*/ lambda$lambdaexample$0,/*MethodHandle*/ (String,String)int); /*MethodType*/ final class LambdaExample$$Lambda$1/1834188994 implements Comparator { private LambdaExample$$Lambda$1/1834188994() public int compare(Object,Object) } public interface Comparator {/*erased*/ int compare(Object o1, Object o2); }
  • 112. @MSkarsaune Runtime implementation LambdaMetaFactory • metaFactory(…) • altMetaFactory(…) InnerClassLambdaMetafactory ASM Lambda Class Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower
  • 114. @MSkarsaune • Possible to back port ? –Capture generated class ? –Compile time generation of inner class! Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower
  • 115. @MSkarsaune Step 1: Source.java public boolean allowLambda() { return compareTo( ) >= 0; } JDK1_8JDK1_ 5 Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower
  • 116. @MSkarsaune Step 2: Special handling boolean mustBackportLambda() { return this.target.compareTo(Target.JDK1_8) < 0; } Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower
  • 117. @MSkarsaune Step 3: Call backport if(!this.attr.mustBackportLambda()) { result = makeMetafactoryIndyCall(...); } else { result = new LambdaBackPorter(...).implementLambdaClass(...); } Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower
  • 118. @MSkarsaune Example implementation private static final class Lambda$$2 implements Comparator<String> { Lambda$$2 { super(); } public int compare(String arg0, String arg1) { return LambdaExample.lambda$lambdaExample$0(arg0, arg1); } public int compare(Object o1, Object o2) { return this.compare((String)o1, (String)o2); } } Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower
  • 119. @MSkarsaune Example invoking public Comparator<String> lambdaExample() { } return LambdaMetafactory.metafactory(...);return new Lambda$$2(); Parse Enter Process Attribute Flow Desugar Generate TransTypes Unlambda Lower
  • 124. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate • <invokedynamic> “playground” 1. @InvokeIndy annotation on method with reference to boostrap method 2. Annotation processor that validates reference 3. Compiler plugin that replaces method invocation with invokedynamic
  • 125. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate @IndyMethod public class SomeService { //must refer to a valid public static method //with certain characteristics @IndyMethod( implementation="no.kantega.jvm.indy.example.SomeProvider", method= "dummyMethod") public static void doStuff() { throw new UnsupportedOperationException("..."); } }
  • 126. @MSkarsaune no.kantega.jvm.indy.compiler.plugin.IndyAnnotationChecker Hooking in the processor: META-INF/services/javax.annotation.processing.Processor: Parse Enter Process Attribute Flow Desugar Generate
  • 127. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate Annotation processor: setup, compliance + mapping @SupportedAnnotationTypes("no....IndyMethod") @SupportedSourceVersion(SourceVersion.RELEASE_8)//Java version public class IndyAnnotationChecker extends AbstractProcessor { //... public boolean process(Set<...> annotations, RoundEnvironment roundEnv) { for (TypeElement annotation : annotations) { for (Element element : roundEnv.getElementsAnnotatedWith(annotation)) { //...raise error if earlier than Java 7 or missing plugin IndyMethod indyMethodRef = element.getAnnotation(IndyMethod.class); if (indyMethodRef != null) { //...check existance of type and compliance of method ... processingEnv.getMessager().printMessage(Kind.ERROR,"...", element); } } //...
  • 128. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate ... <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <!-- Disable annotation processing for ourselves. --> <compilerArgument>-proc:none</compilerArgument> </configuration> </plugin> </plugins> </build> ... Disable annotation processing in the project that implements the plugin (!): pom.xml :
  • 129. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate • Compiler plugin –Hook straight into the compilation process –Respond to events from compilation process –Make changes to AST
  • 130. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate no.kantega.jvm.indy.compiler.plugin.IndyPlugin Hooking in the plugin: META-INF/services/com.sun.source.util.Plugin:
  • 131. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate public class IndyPlugin implements Plugin { public String getName() { return "IndyPlugin"; } public void init(JavacTask paramJavacTask, String... paramArrayOfString) { paramJavacTask.addTaskListener( new GenerateInvokeDynamicHandler()); } } Typical plugin definition: • Unique name • Delegate to task listener(s)
  • 132. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate public class GenerateInvokeDynamicHandler implements TaskListener { public void started(TaskEvent start) { if(start.getKind() == Kind.GENERATE) { for (Tree tree : start.getCompilationUnit().getTypeDecls()) { tree.accept(new IndyMethodInvocationReplacer(), tree); } } } Task listener: • Receive callback, check stage • Insert visitor to process ASTs
  • 133. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate public class IndyMethodInvocationReplacer extends TreeScanner { public Object visitMethodInvocation(MethodInvocationTree node, Tree p) { {//...various checks on the method call //...see if annotation processor has created mapping for it MethodSymbol replacementMethod = IndyMethodMappings.getInstance(). mappingFor((MethodSymbol) identifier.sym); if(replacementMethod!= null) {//insert reference to bootstrap identifier.sym=new Symbol.DynamicMethodSymbol(...); } } } } return super.visitMethodInvocation(node, p); } } Visitor: • Make modifications
  • 134. @MSkarsaune Parse Enter Process Attribute Flow Desugar Generate <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <compilerArgs> <arg>-Xplugin:IndyPlugin</arg> </compilerArgs> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> Users: • Enable plugin in compilation
  • 136. @MSkarsaune Wrap Up • The Java compiler is written in pure Java • Compilation is done in phases • Programming language advances (syntactic sugar) require good compiler support • Lambdas are compiled in a forward compatible manner • Annotation processors and compiler plugins may be used to tailor the compilation process to specific needs
  • 137. @MSkarsaune Resources • OpenJDK • Source: http://hg.openjdk.java.net/ • Compiler hacking tutorial • http://www.ahristov.com/tutorial/java-compiler.html • Sample code: • https://github.com/skarsaune/goto • https://github.com/skarsaune/indy-plugin • Slide pack: • http://www.slideshare.net/MartinSkarsaune • 60 minute video (Devoxx) : • https://youtu.be/gGTDQq6ZjIk
  • 139. @MSkarsaune Thank You for Your Time!Martin Skarsaune Java Developer and Co-Owner

Notas do Editor

  1. Hello everyone. My name is Martin Skarsaune, developer working for Kantega. Today we are going to have a peek into the compiler. I assume everyone here rely on a Java compiler in their everyday work. Just out of curiosity, have anyone had a look at the compiler source code ? I guess a lot of clever developers out here have read articles, have debugged a lot of Java applications and disassempled class files to see what your Java code turns into on the other end. So some of the stuff may be known to you, never the less I think it is worth while to look at the process step by step from the inside and see with out own eyes what goes on.
  2. A compiler is a tool that accepts input in some sort of programming language and produces output targeted for another language or instruction set.
  3. A common compiler architecture is to try to decouple the input from the output. The front end deals with specifics handling, checks and optimizations for the given programming language, and the back end deals with generation, dependencies and optimizations for a given target platform. This separation is an obvious choice for compilers that generate native code. I was involved in a big project over several years, where we developed tools and routines for automated translation from Smalltalk to Java. In that project we did exactly this, we reused the parser and internal representation from the built in Smalltalk compiler, but instead of generating Smalltalk byte codes, we generated Java source code.