您的位置:首页 > 其它

第10章, 早期(编译期)优化

2017-08-26 15:05 183 查看

1、概述:

编译过程的编译器:

1、前端编译器:Sun的Javac、Eclipse JDT中的增量式编译器(ECJ) (.java文件变为*.class过程)
2、JIT编译器:HotSpot VM 的C1、C2编译器(.class文件变成机器码的过程)
3、AOT编译器:GNU Compiler for the java(GCJ)、Excelsior JET(.java文件直接变成机器码的过程)

2、Javac编译器

编译器过程大致分为三个过程

1、解析与填充符号表过程
2、插入式注解处理器的注解处理过程
3、分析与字节码生成过程

2.1 解析与填充符号表

1、词法、语法分析

2、填充符号表

总结:不恰当比喻---将不同大小苹果先检出来,按照放入不同筐内。

2.2 注解处理器

注解与普通代码类似,根据不同注解重复修改语法树。(塑像进行雕刻,而注解是刀,塑像是语法树)

2.3 语义分析与字节码生成

表示代码正确,还要符合类型之间关系

int a=1;

boolean b = false;

char c = 2;

int d = a+c (编译正确)

int d = b+c(编译异常)

1、标注检查

常量折叠:例如 int a= 1+2; 代表是 int a =3

2、数据及控制流分析

3、解语法糖 

定义:增加程序可读性,对功能没有的影响的语法

4、字节码生成

3、java语法糖的味道

3.1、泛型与类型擦除

真实泛型:就是泛型一直存在到运行期,List<int>与List<String>就是不同类型,它们有自己的虚方法表和类型数据。

伪泛型:java语言的泛型,它只存在于源码中,后期编译会替换原来的原生类型,并且在相应位置插入强制转换代码,这就是java类型擦除

package com.jack;

import java.util.HashMap;
import java.util.Map;

public class Main {
public static void main(String[] args) throws Throwable{
Map<String, String> map = new HashMap<String,String>();
map.put("hello", "你好");
map.put("how are you?", "点点滴滴");
System.out.printf(map.get("hello"));
System.out.printf(map.get("how are you?"));

}
}


编译成字节码文件后反编译为:
package com.jack;

import java.util.HashMap;

public class Main {
public static void main(String[] arg) throws Throwable {
HashMap arg0 = new HashMap();
arg0.put("hello", "你好");
arg0.put("how are you?", "点点滴滴");
System.out.printf((String) arg0.get("hello"), new Object[0]);
System.out.printf((String) arg0.get("how are you?"), new Object[0]);
}
}List<Integer> 和List<String>代表同一个类
import java.util.List;

public class GenericTypes {

public static void method(List<String> list) {
System.out.printf("invoke method(List<String> list)");
}

public static void method(List<Integer> list) {
System.out.printf("invoke method(List<Integer> list)");
}
}会出现编译错误 :Erasure of method method(List<Integer>) is the same as another method in type (表示擦拭泛型后代表相同类)

3.3 自动装箱、拆箱与遍历循环

import java.util.Arrays;
import java.util.List;

public class Main {
public static void main(String[] args) throws Throwable{
List<Integer> list = Arrays.asList(1,2,3,4);
int sum =0;
for (int i: list){
sum +=i;
}
System.out.println(sum);
}
}


编译后的代码
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class Main {
public static void main(String[] arg) throws Throwable {
List arg0 = Arrays
.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4)});
int arg1 = 0;

int arg3;
for (Iterator arg2 = arg0.iterator(); arg2.hasNext(); arg1 += arg3) {
arg3 = ((Integer) arg2.next()).intValue();
}

System.out.println(arg1);
}
}

以上一共包含泛型、自动装箱、自动拆箱、遍历循环与变长参数的五种语法糖

public class Main {
public static void main(String[] args) throws Throwable{
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 222;
Integer f = 222;
Long g = 3L;
System.out.printf("c==d : %s\n", c==d);
System.out.printf("e==f : %s\n", e==f);
System.out.printf("e.equals(f) : %s\n",e.equals(f));
System.out.printf("c == (a+b) : %s\n", c==(a+b));
System.out.printf("c.equals(a+b): %s\n", c.equals(a+b));
System.out.printf("g == (a + b): %s\n", g == (a + b));
System.out.printf("g.equals(a+b): %s\n", g.equals(a+b));
}
}

字节码反编译:

public class Main {
public static void main(String[] arg) throws Throwable {
Integer arg0 = Integer.valueOf(1);
Integer arg1 = Integer.valueOf(2);
Integer arg2 = Integer.valueOf(3);
Integer arg3 = Integer.valueOf(3);
Integer arg4 = Integer.valueOf(222);
Integer arg5 = Integer.valueOf(222);
Long arg6 = Long.valueOf(3L);
System.out.printf("c==d : %s\n", new Object[]{Boolean.valueOf(arg2 == arg3)});
System.out.printf("e==f : %s\n", new Object[]{Boolean.valueOf(arg4 == arg5)});
System.out.printf("e.equals(f) : %s\n", new Object[]{Boolean.valueOf(arg4.equals(arg5))});
System.out.printf("c == (a+b) : %s\n",
new Object[]{Boolean.valueOf(arg2.intValue() == arg0.intValue() + arg1.intValue())});
System.out.printf("c.equals(a+b): %s\n",
new Object[]{Boolean.valueOf(arg2.equals(Integer.valueOf(arg0.intValue() + arg1.intValue())))});
System.out.printf("g == (a + b): %s\n",
new Object[]{Boolean.valueOf(arg6.longValue() == (long) (arg0.intValue() + arg1.intValue()))});
System.out.printf("g.equals(a+b): %s\n",
new Object[]{Boolean.valueOf(arg6.equals(Integer.valueOf(arg0.intValue() + arg1.intValue())))});
}

日志:

c==d : true
e==f : false
e.equals(f) : true
c == (a+b) : true
c.equals(a+b): true
g == (a + b): true
g.equals(a+b): false


总结:

1、如果是对象还是用equals进行比较保险。
2、无论是Integer,Long的装箱拆箱都是基于【-128,127】范围有效
Integer a = 128;
Integer b =128;
a==b 为false

3.3、条件编译

public class Main {
public static void main(String[] args) throws Throwable{
if(true){
System.out.printf("模块一");
} else {
System.out.printf("模块二");
}
}
}


编译后:
public class Main {
public static void main(String[] args) throws Throwable{
System.out.printf("模块一");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: