首页 > 其他分享 >jvm 指令与指令执行

jvm 指令与指令执行

时间:2023-08-21 21:11:48浏览次数:40  
标签:局部变量 sayHello 指令 jvm 执行 方法

运行时内存结构

在了解jvm指令之前,需要先了解java虚拟机运行时内存的结构,根据jvm规范(java se8),运行时数据区给每个线程分配了不同的区域,比如PC寄存器、JVM栈,本地方法栈,线程共有的部分有堆与方法区。

栈上每个函数调用都有一个帧作为对应数据结构,每个帧都包括局部变量表与操作数栈,这部分在编译的时候就可以确定了,局部变量表用来保存方法中的局部变量,以及方法参数。当一个方法刚开始执行的时候,操作数栈是空的,在方法执行过程中,会有各种字节码指令往操作数栈中写入和取出数据,也就是入栈和出栈操作。

https://www.cnblogs.com/jiuxing/p/13899711.html

可以使用jclasslib来看到方法的局部变量表:

由于方法是static方法,所以局部变量表的第一个元素并不是this;

非static方法:

jvm指令执行

根据字节码解释器的工作流程:

do { 
  atomically calculate pc and fetch opcode at pc; 
  if (operands) 
    fetch operands; 
  	execute the action for the opcode; 
} while (there is more to do);

指令操作的对象有部分就是局部变量表上的数据,然后执行方法会在栈上进行计算,这种方式可以描述为基于栈的字节码解释执行。

比如一个简单的执行加法的函数:

    public int add(int i, int j) {
        return i+j;
    }

指令

0 iload_1

1 iload_2

2 iadd

3 ireturn

iload_1 iload_2 分别把两个局部变量表的内容放在栈上,然后执行iadd操作,取出栈顶两个元素,相加后放回栈顶,最后执行ireturn,返回栈顶的int

每个栈帧都包含了一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态链接。

 static abstract class Human {

        abstract void sayHello();
    }

    static class Man extends Human {

        @Override
        void sayHello() {
            System.out.println("Man say hello!");
        }
    }

    static class Woman extends Human {
        @Override
        void sayHello() {
            System.out.println("Woman say hello!");
        }
    }

    private static void testHumanSayHello() {
        Human man = new Man();
        Human woman = new Woman();
        man.sayHello();
        woman.sayHello();

        man = new Woman();
        man.sayHello();
    }

编译出的字节码为

 0 new #3 <com/sankuai/example/rasp/pigeon/test/starter/util/ASMDemo$Man>
 3 dup
 4 invokespecial #4 <com/sankuai/example/rasp/pigeon/test/starter/util/ASMDemo$Man.<init> : ()V>
 7 astore_0
 8 new #5 <com/sankuai/example/rasp/pigeon/test/starter/util/ASMDemo$Woman>
11 dup
12 invokespecial #6 <com/sankuai/example/rasp/pigeon/test/starter/util/ASMDemo$Woman.<init> : ()V>
15 astore_1
16 aload_0
17 invokevirtual #7 <com/sankuai/example/rasp/pigeon/test/starter/util/ASMDemo$Human.sayHello : ()V>
20 aload_1
21 invokevirtual #7 <com/sankuai/example/rasp/pigeon/test/starter/util/ASMDemo$Human.sayHello : ()V>
24 new #5 <com/sankuai/example/rasp/pigeon/test/starter/util/ASMDemo$Woman>
27 dup
28 invokespecial #6 <com/sankuai/example/rasp/pigeon/test/starter/util/ASMDemo$Woman.<init> : ()V>
31 astore_0
32 aload_0
33 invokevirtual #7 <com/sankuai/example/rasp/pigeon/test/starter/util/ASMDemo$Human.sayHello : ()V>
36 return

可以看到在17与21行执行sayHello方法时,都是使用的invokevirtual,根据jvm虚拟机规范对指令的说明,执行invokevirtual,会把对象放在操作数栈的顶部,执行方法时先找到这个objectref对应的类C(从持有的字符串常量池的引用中查找),如果C中包含这个方法的重写方法,就调用,否则从下往上一次寻找类C的父类有无这个方法,如果有就调用。对于接口来说,需要找到一个方法实现并且方法描述里不包含abstract。

jvm的指令规范:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5

参考

https://tobebetterjavaer.com/jvm/how-jvm-run-zijiema-zhiling.html

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5

标签:局部变量,sayHello,指令,jvm,执行,方法
From: https://www.cnblogs.com/cyyyyx/p/17647095.html

相关文章

  • 深入学习JVM01
    一、云时代的JVM云时代的来临也给Java带来了不小的挑战,速度、内存、部署与管理的问题逐渐变成了Java的负累。不过它并没有坐以待毙,而是选择积极地适应新时代,引入更多新特性来应对这些挑战。......
  • c2工具sliver 执行木马命令后会弹窗一闪而过
    向木马发出指令后,如果是cmd命令会有一个黑窗口一闪而灭,不利于木马隐藏,需要将executeHandler从handlers.go拷贝到handlers_windows.go里,核心代码为cmd.SysProcAttr=&syscall.SysProcAttr{HideWindow:true}表示隐藏命令弹窗funcexecuteHandler(data[]byte,respRPCRe......
  • 记:Elasticsearch 的 告警机制 和 jvm 内存分配
    Elasticsearch的告警机制导致的更新失败问题总结:由于测试环境资源占用比例过高导致elasticsearch触发保护机制,导致的更新失败的问题Es告警日志:查看服务器资源使用情况:此时Es所在的挂载磁盘已经占用了95%,Es默认的保护机制:属性名属性值(可配置为固定值)含义保......
  • Vue 中请求同步执行解决方案
    有很多小伙伴在使用Vue的时候都会遇到一种情况,form表单修改回显时,某个下拉框里的内容回显乱码,这是因为Vue是的请求方法是异步请求:简单来说,form表单内容先获取了出来,而项目阶段的下拉框随后才获取出来//表单<el-col:span="12"> <el-form-item:label="$t('项目阶段')"prop=......
  • JS的执行还分是谁发起的?
    这一部分首先我们考虑一下,如果我们是浏览器或者Node的开发者,我们该如何使用JavaScript引擎。当拿到一段JavaScript代码时,浏览器或者Node环境首先要做的就是;传递给JavaScript引擎,并且要求它去执行。然而,执行JavaScript并非一锤子买卖,宿主环境当遇到一些事件时,会继续......
  • 浅谈Angular模板指令:ng-template和ng-container的用法
    本篇文章带大家简单了解一下Angular模板的ng-template和ng-container指令,介绍一下ng-template和ng-container指令使用方法。ng-template指令简介ng-template是一个Angular结构型指令,用来渲染HTML。它永远不会直接显示出来。事实上,在渲染视图之前,Angular会把ng-template......
  • 8-21|Python使用管道如何执行此删除目录
    要在Python中使用管道执行此命令,你可以利用`subprocess`模块。下面是一个示例,展示如何在Python中执行这个命令:```pythonimportsubprocessdirectory="path_to_directory"#构建命令cmd=f'cd{directory}&&del/f/s/q*.*&&for/d%xin(*)dormdir/s/q"%x&quo......
  • 《深入浅出Java虚拟机 — JVM原理与实战》带你攻克技术盲区,夯实底层基础 —— 吃透cla
    前言介绍了解Java代码如何编译成字节码并在JVM上执行是非常重要的。这种理解可以帮助我们理解程序执行时发生的情况,确保语言特性符合逻辑,并在进行讨论时能够全面考虑各种因素和副作用。本文将深入探讨Java代码编译成字节码并在JVM上执行的过程。如果您对JVM的内部结构和字节码执行......
  • PL/SQL执行计划查看
    一.如何查看PLSQL的执行计划在SQlWindow窗口输入sql语句,然后按键"F5",就会进入执行计划查看界面。二.界面说明首先我们看第二行有几个属性可以选“Tree”、“HTML”、“Text”、“XML”。这几个里面的核心数据是一样的,不同的只是对核心数据的展示方式,分别为Tree、HTML、Text、......
  • 常见字符串操作指令
    常见的字符串操作指令在x86汇编中有很多,以下是其中一些常见的指令:MOVSB/MOVSW/MOVSD:将一个字节/字/双字从源地址复制到目的地址,并递增源和目的指针。REPMOVS:重复执行MOVSB/MOVSW/MOVSD指令,用于复制整个字符串。STOSB/STOSW/STOSD:将一个字节/字/双字的值存储到目的地址......