JVM解释器(不是JIT编译器)实际上做什么?

JVM解释器(不是JIT编译器)实际上做什么?,jvm,interpreter,Jvm,Interpreter,请注意,我的问题是关于JVM解释器的,而不是关于JIT编译器的。JIT编译器将java字节码转换为本机代码。因此,这必须意味着JVM中的解释器不会将字节码转换为机器码。因此问题就来了:从本质上讲,口译员做什么?如果有人能帮我回答这个问题,用一个简单的字节码示例,相当于1+1=2,即解释器在执行这个加法操作时做了什么?(我的隐含问题是,如果解释器不翻译为机器代码,那么哪个CPU执行添加操作,那么该操作是如何执行的?实际执行什么机器代码来支持该添加操作?表达式1+1将编译为以下字节码: iconst

请注意,我的问题是关于JVM解释器的,而不是关于JIT编译器的。JIT编译器将java字节码转换为本机代码。因此,这必须意味着JVM中的解释器不会将字节码转换为机器码。因此问题就来了:从本质上讲,口译员做什么?如果有人能帮我回答这个问题,用一个简单的字节码示例,相当于1+1=2,即解释器在执行这个加法操作时做了什么?(我的隐含问题是,如果解释器不翻译为机器代码,那么哪个CPU执行添加操作,那么该操作是如何执行的?实际执行什么机器代码来支持该添加操作?

表达式
1+1
将编译为以下字节码:

iconst_1
iconst_1
add
(实际上,它将编译成
iconst_2
,因为Java编译器执行常量折叠,但为了回答这个问题,我们忽略它。)

因此,为了确切地了解解释器对这些指令做了什么,我们应该看看。有关代码< > COSTRY1和<代码> Audio/Cuff>开始,分别,所以让我们看一下:

定义OPC常量(操作码、常量类型、值)\ 案例(操作码):\ 设置_STACK_35;##const_type(值,0)\ 更新PC和TOS并继续(1,1); OPC常量n(_iconst_m1,INT,-1); OPC常数(_iconst_0,INT,0); OPC常量(_iconst_1,INT,1); //继续计算其他几个常数 //... #定义OPC_INT_二进制文件(opcname、opname、test)\ 案例(_i###opcname):\ 如果(test&(STACK_INT(-1)==0)){\ VM_JAVA_错误(vmSymbols::JAVA_lang_算术异常()\ “/按零”,注_div0Check _trap)\ } \ 设置堆栈INT(VMint###opname)(堆栈INT(-2)\ 堆栈_INT(-1))\ -2); \ 更新PC和TOS并继续(1,-1)\ //对于long而不是int也一样 OPC_INT_二进制(add,add,0); //其他操作员 整个过程都在一个switch语句中,该语句检查当前指令的操作码

如果我们扩展宏魔法,用一个极其简化的模板替换周围的代码,并做出一些简化假设(例如堆栈仅由
int
s组成),我们最终会得到如下结果:

enum操作码{
_iconst_1,_iadd
};
// ...
int*stack=newint[计算最大堆栈大小();
堆栈的大小\u t top\u=0;
大小\u t程序\u计数器=0;
while(程序计数器<程序大小){
开关(操作码[程序计数器]){
案例1:
//设置堆栈INT(1,0);
堆栈[堆栈的顶部]=1;
//更新PC和TOS并继续(1,1);
程序计数器+=1;
_堆栈的顶部_+=1;
打破
个案(iadd):
//设置堆栈INT(VMintAdd(堆栈INT(-2),堆栈INT(-1)),-2);
堆栈[top\u of_stack-2]=堆栈[top\u of_stack-1]+堆栈[top\u of_stack-2];
//更新PC和TOS并继续(1,-1);
程序计数器+=1;
_堆栈的顶部_+=-1;
打破
}
因此,对于
1+1
而言,操作顺序为:

stack[0]=1;
堆栈[1]=1;
堆栈[0]=堆栈[1]+堆栈[0];

top\u of_stack
将是1,因此我们将以一个包含值
2
作为其唯一元素的堆栈结束。

实际的机器代码是解释器的一部分。只需考虑一个包含switch语句的循环,每个现有字节码指令都有一个案例,在那里执行操作或调用subgrar是