Java编译器的行为------第一节:方法

    xiaoxiao2021-12-15  30

    可以将Java虚拟机看做一个组件,他的存在实现了Java程序“一次编译,到处执行”的目标。Oracle的JDK软件包含两部分内容:一部分是将Java源代码编译成字节码文件(Java虚拟机指令集文件)的编译器,一部分是用于实现Java虚拟机运行时环境(JRE)。编译器和虚拟机两者相辅相成,下面是Java编译器的行为:

    1、接收参数

    如果传递n个参数给某个实例方法,则当前栈帧会按照约定的顺序接收这些参数,并将它们保存在方法的第1个到第n个局部变量之中,而他的第0个局部变量用于存放自身实例的引用(Java语言中访问自身实例的关键字this就是通过第0个局部变量实现的)。

    如果传递n个参数给一个类方法(static),则当前栈帧也会按照约定的顺序接收这些参数,但将它们保存在方法的第0个到第n-1个局部变量之中(因为类方法不依赖于实例,不存在自身实例引用这一概念)。

    2、方法调用

    普通实例方法调用是在运行时根据对象类型进行分派的(相当于动态绑定),这类方法的调用是通过虚拟机指令集中的invokevirtual指令完成,该指令带有一个表示索引的参数,该参数表示此方法的符号引用在运行时常量池中的索引位置,通过符号引用就可以获得方法所在对象类型的名称、方法名称和方法描述符。

    注:编译器并不需要获得类实例的内部布局,他只需产生方法的符号引用并存储到常量池中即可。而运行时常量池项会在执行时转换成调用方法的实际地址。

    类方法(static)调用过程和普通实例调用方法类似,区别在两个方面:类方法调用是通过虚拟机指令集中的invokestatic指令完成;类方法调用时无需传递this参数。

    实例初始化方法是有编译器调用的,其调用是通过虚拟机指令集中的invokespecial指令完成。同时,父类的实例方法和实例的私有方法调用也是通过invokespecial指令完成。

    注:使用invokespecial指令的方法都是实例方法,故其第0个局部变量都为this。

    注:编译器在生成invokevirtual指令时,也会生成这个指令所引用的描述符,这个描述符包含方法实际参数和返回类型。编译器在方法调用时不会处理参数的类型转换问题,只是简单的将参数压人操作数栈,且不改变其类型。而对于描述符的解析要等到运行时才会进行。

    转载请注明原文地址: https://ju.6miu.com/read-1000019.html

    最新回复(0)