JAVA代码的执行分为三个大的步骤
一、代码编译为class文件
根据jvm规范,不同厂商提供了不同的规范。例如在sun jdk中是javac,eclipse用的是jdt
简单分为如下步骤:
1、分析和输入到符号表
2、注解处理
3、语义分析和生产class文件
生成的class文件,不仅仅存放了java的字节码,同时还提供了 结构信息、元数据、方法信息
三、执行class文件
二、装载class文件-classloader
类的加载主要是通过如下的几个过程 装载、连接、初始化,其中初始化可以是提前的静态初始化,或者在方法第一次调用的时候初始化
类的加载主要通过ClassLoader及其子类完成的
分为 Bootstrap Class Loader,Extension Class Loader、System Class Loader、以及User-Defined Class Loader
1、解释执行
在源码编译阶段被编译成jvm的字节码,供解释执行,解释执行特点就是占用内存较少
2、编译执行
分为client compiler(-client)和 server compiler(-server)两种方式
client compiler称为C1是比较轻量级的优化
server compiler称为C2是比较激进的优化
编译执行在运行时进行,通常称为JIT编译器。我们可以通过xint来进行显式的禁用或者启动。因为对执行不频繁的代码采用解释执行的方式,因此sun jdk又称作hotspot vm。
C1的常见优化手段是有方法内联、去虚拟化、冗余消除
方法内联:就是将两个类之间的调用,直接整合成一个类
去虚拟化:就是将接口的唯一实现直接编译了
冗余消除:就是将一些代码根据运行时状况直接删除,例如判定执行的debug,如果运行时不执行,直接将其削除。
C2比较重量级,默认C2在硬件达到2G以上内存,双核的机器上自动安装开启。
C2在C1的基础上又进行了标量替换、栈上分配、同步削除等激进优化手段,运行后C1,C2编译出来的机器码不符合优化条件,会进行逆优化。可以是C2退回到C1,C1退回到解释执行。
3、反射执行
反射耗费性能是因为他要去校验类的权限、方法的权限是否违规,本身在jdk6之后基本上无特别大的性能损耗
将反射的方法cache后和直接调用没啥区别。
总的来说:
1、JIT执行是在程序执行一定的时间之后才能看出调优的效果。
2、解释执行不耗费内存,内存用的较少
3、可以直接指定jdk用C1还是C2进行启动优化