首先日常编写的代码都是高级代码,机器无法识别,高级代码都需要先编译成汇编代码,再编译为机器代码供计算机运行。
在JAVA中,就是先将边写的.java文件编译成.class文件,再借助JVM解释运行。
Java作为跨平台语言,是因为JVM只关注字节码文件,从此反推JVM也可以解释其他语言编译出的字节码文件(只要字节码文件符合规范,如开头cafebabe)就可以通过一个JVM运行多种代码。
整体流程:
先借助前端编译器将.java文件编译成.class文件(即字节码文件),交由类加载器子系统(将class加入内存,产生大的class对象)。
在运行时数据区有如下部分:
多线程共享:
方法区(存class实例)
堆
线程独有:
Java栈、虚拟机栈
本地方法栈
程序计数器
类加载过后由执行引擎进行操控,将高级代码转为机器代码进行执行。
执行引擎:分为三部分:
解释器:解释运行(逐行翻译字节码进行执行,保证相应时间)
JIT即时编译器(即编译器后端):编译执行(热点代码二次编译缓存至方法区内,保证效率)
此外对应内部的本地方法栈,还有本地方法接口、本地方法库。
.java编译过程(汇编):
词法分析->语法分析->语法树->语义分析->注解抽象语法树->字节码生成器
JVM翻译过程:
类加载器->字节码校验器->执行引擎->控制os
指令集架构:
首先介绍n地址指令。
在内存中地址指向引用操作数,n地址即表示用n个地址指向操作数。
栈式指令集:
0地址指令(只用操作栈,无需指向)
不用硬件支持(移植性好)
指令多、指令集小(指令集采用8位对齐)
寄存器指令集:
1、2、3地址指令
性能好
依赖硬件(需要内存存地址指向)
指令少、指令集大(指令集采用16位对齐)
JVM生命周期:
启动——>执行——>退出
启动:引导类加载器、创建初始类(并不是Object,很多)
执行:执行java程序(实际上是开启一个java虚拟机进程进行程序的执行)
退出:
被动:程序结束、程序异常
主动:调用系统函数如:halt()、exit()
JVM发展历程:
初代Classic VM:
只有解释器,响应快(用JIT需外挂,导致两者无法配合工作)
Exact VM:
①可知内存中数据具体类型(知道内存中的数是具体数据还是引用地址关系)
②采用解释器、JIT混合使用
HotSpot VM:
最常用,顾名思义热点虚拟机(多用途)
JRockit:
专用于服务器,只用编译执行(JIT),专注于性能、效率
高性能,低硬件成本
J9:同多用途,只限制于IBM自身的环境高速
aliJVM:专用于淘宝等,国产
创新GCIH:Invisible heap:
①将生命周期长的对象放到heap之外,将GC效率加快。
②其中的对象可在多个虚拟机进程共用