`

Java栈和局部变量操作(一)

 
阅读更多

Java栈和局部变量操作

Java虚拟机是基于栈的机器,几乎所有Java虚拟机的指令都与操作数栈相关。栈操作包括把常量压入操作数栈、执行通用的栈操作、在操作数栈和局部变量之间往返传输值。

1常量入栈操作:

操作码在执行常量入栈操作之前,使用三种方式指明常量的值:常量值隐含包含在操作码内部、常量值在字节码中如同操作数一样跟随在操作码之后,或者从常量池中取出常量。

1.1常量值隐含包含在操作码内部:

将一个字长的常量压入栈

操作码

操作数

说明

iconst_m1

(无)

int类型值-1压入栈

iconst_0

(无)

int类型值0压入栈

iconst_1

(无)

int类型值1压入栈

iconst_2

(无)

int类型值2压入栈

iconst_3

(无)

int类型值3压入栈

iconst_4

(无)

int类型值4压入栈

iconst_5

(无)

int类型值5压入栈

fconst_0

(无)

float类型值0压入栈

fconst_1

(无)

float类型值1压入栈

fconst_2

(无)

float类型值2压入栈

将两个字长的常量压入栈

操作码

操作数

说明

lconst_0

(无)

long类型值0压入栈

lconst_1

(无)

long类型值1压入栈

dconst_0

(无)

double类型值0压入栈

dconst_1

(无)

double类型值1压入栈

给一个对象引用赋空值时会用到aconst_null指令

将空(null)对象引用压入栈

操作码

操作数

说明

aconst_null

()

将空(null)对象引用压入栈

例如下面代码:

publicclassStackTest {

/**

* @paramargs

*/

publicstaticvoidmain(String[] args) {

//TODOAuto-generated method stub

inti = 0;

intj = 4;

intk;

k= i + j;

floata = 0;

floatb = 1;

floatc =a + b;

longx = 0;

longy = 1;

longz =x + y;

Stringstring= null;

}

}

javap工具查看其字节码为:

Compiledfrom "StackTest.java"

publicclass StackTest extends java.lang.Object{

publicStackTest();

Code:

0: aload_0

1: invokespecial #8;//Method java/lang/Object."<init>":()V

4: return

publicstatic void main(java.lang.String[]);

Code:

0: iconst_0 //常量int类型的0入栈

1: istore_1 //弹出栈顶元素0存入位置1的局部变量中

2: iconst_4 //常量int类型的4入栈

3: istore_2 //弹出栈顶元素4存入位置2的局部变量中

4: iload_1 //从位置为1的局部变量中取出元素int类型的0压入栈

5: iload_2 //从位置为2的局部变量中取出元素int类型的4压入栈

6: iadd //从栈顶弹出两个元素然后做加法,把结果压入栈

7: istore_3 //弹出栈顶元素4存入位置为3的局部变量中

8: fconst_0 //常量float类型的0入栈

9: fstore 4 //弹出栈顶元素0存入位置为4的局部变量中

11: fconst_1 //常量float类型的1入栈

12: fstore 5 //弹出栈顶元素1存入位置为5的局部变量中

14: fload 4 //从位置为4的局部变量中取出元素float类型的0压入栈

16: fload 5 //从位置为5的局部变量中取出元素float类型的1压入栈

18: fadd //从栈顶弹出两个元素然后做加法,把结果压入栈

19: fstore 6 //弹出栈顶元素1存入位置为3的局部变量中

21: lconst_0 //常量long类型的0入栈

22: lstore 7 // 弹出栈顶元素0存入位置为78的局部变量中

24: lconst_1 //常量long类型的1入栈

25: lstore 9 // 弹出栈顶元素0存入位置为910的局部变量中

27: lload 7 //从位置为78的局部变量中取出元素long类型的0压入栈

29: lload 9 //从位置为910的局部变量中取出元素long类型的1压入栈

31: ladd //从栈顶弹出两个元素然后做加法,把结果压入栈

32: lstore 11 //弹出栈顶元素1存入位置为1112的局部变量中

34: aconst_null //null对象引用压入栈

35: astore 13 //弹出栈顶元素null存入位置为13的局部变量中

37: return

}

1.2常量值在字节码中跟随在操作码之后:

byteshort类型常量压入栈

操作码

操作数

说明

bipush

一个byte类型的数

byte类型的数转换为int类型的数,然后压入栈

sipush

一个short类型的数

short类型的数转换为int类型的数,然后压入栈

1.3从常量池中取出常量

操作码

操作数

说明

ldc

无符号8位数indexbyte

从由indexbyte指向的常量池入口中取出一个字长的值,然后将其压入栈

ldc_w

无符号16位数indexshort

从由indexshort指向的常量池入口中取出一个字长的值,然后将其压入栈

ldc2_w

无符号16位数indexshort

从由indexshort指向的常量池入口中取出两个字长的值,然后将其压入栈

这三个操作码是从常量池中取出常量,然后将其压入栈,这些操作码的操作码表示常量池索引,Java虚拟机通过给定的索引查找相应的常量池入口,决定这些常量的类型和值,并把它们压入栈。

常量池索引是一个无符号值,ldcldc_w是把一个字长的项压入栈,区别在于:ldc的索引只有一个8位,只能指向常量池中1255范围的位置。ldc_w的索引有16位,可以指向165535范围的位置。

例如下面代码:

publicclassStackTest {

/**

* @paramargs

*/

publicstaticvoidmain(String[] args) {

//TODOAuto-generated method stub

bytei = 125;

bytej = -128;

int k =i + j;

shorta = 32767;

shortb = - 32768;

intc =a + b;

int x = 2147483647;

inty = -2147483648;

intz =x + y;

longI = 2147483648L;

longJ = -2147483649L;

longK =I + J;

}

}

javap工具查看其字节码为:

Compiledfrom "StackTest.java"

publicclass StackTest extends java.lang.Object{

publicStackTest();

Code:

0: aload_0

1: invokespecial #8;//Method java/lang/Object."<init>":()V

4: return

publicstatic void main(java.lang.String[]);

Code:

0: bipush 125 //byte类型的255转换成int类型压入栈

2: istore_1 //弹出栈顶元素255存入位置为1的局部变量中

3: bipush -128//byte类型的-128转换成int类型压入栈

5: istore_2 //弹出栈顶元素-128存入位置为2的局部变量中

6: iload_1 //取出位置为1的局部变量中的数压入栈

7: iload_2 //取出位置为2的局部变量中的数压入栈

8: iadd //从栈顶弹出两个元素然后做加法,把结果压入栈

9: istore_3 //弹出栈顶元素存入位置为3的局部变量中

10: sipush 32767//short类型的32767转换成int类型压入栈

13: istore 4 //弹出栈顶元素32767存入位置为4的局部变量中

15: sipush -32768/short类型的-32768转换成int类型压入栈

18: istore 5 //弹出栈顶元素-32768存入位置为5的局部变量中

20: iload 4 //取出位置为4的局部变量中的数压入栈

22: iload 5 //取出位置为5的局部变量中的数压入栈

24: iadd //从栈顶弹出两个元素然后做加法,把结果压入栈

25: istore 6 /弹出栈顶元素存入位置为6的局部变量中

27: ldc #16;//int 2147483647 //从常量池索引16的位置取出2147483647压入栈

29: istore 7 //弹出栈顶元素2147483647存入位置为4的局部变量中

31: ldc #17;//int -2147483648 //从常量池索引17的位置取出-2147483648压入栈

33: istore 8 //弹出栈顶元素-2147483648存入位置为8的局部变量中

35: iload 7 //取出位置为7的局部变量中的数压入栈

37: iload 8 //取出位置为8的局部变量中的数压入栈

39: iadd //从栈顶弹出两个元素然后做加法,把结果压入栈

40: istore 9 //弹出栈顶元素存入位置为9的局部变量中

42: ldc2_w #18;//long 2147483648l //从常量池索引18的位置取出long类型的2147483648L压入栈

45: lstore 10 //弹出栈顶元素2147483648L存入位置为1011的局部变量中

47: ldc2_w #20;//long -2147483649l //从常量池索引20的位置取出long类型的-2147483649L压入栈

50: lstore 12 //弹出栈顶元素-2147483649L存入位置为1213的局部变量中

52: lload 10 //取出位置为1011的局部变量中的数压入栈

54: lload 12 //取出位置为1213的局部变量中的数压入栈

56: ladd //从栈顶弹出两个元素然后做加法,把结果压入栈

57: lstore 14 //弹出栈顶元素存入位置为1415的局部变量中

59: return

}

分享到:
评论

相关推荐

    浅谈java中的局部变量和全局变量

    浅谈java中的局部变量和全局变量 Java 中的变量可以分为两大类:局部变量和全局变量。理解这两种变量的概念、生存时间和创建位置是java开发者必须具备的基本知识。下面我们将对java中的局部变量和全局变量进行详细...

    java 栈的实现和应用

    Java栈是一种基于后进先出(LIFO)原则的数据结构,它在计算机科学和编程中具有广泛的应用。本文将深入探讨Java中栈的实现以及其在实际应用中的使用。 首先,我们来理解栈的基本概念。栈是一种特殊类型的线性数据...

    Java栈详解Java栈详解.doc

    Java栈是Java虚拟机(JVM)内存模型的重要组成部分,主要负责存储方法调用过程中的局部变量、操作数和方法返回信息。栈的特点是后进先出(LIFO),每个线程都有自己的独立Java栈,确保了线程安全的数据存储。 1. **...

    局部变量线程安全测试

    由于每个线程都有自己的独立的调用栈,因此,从理论上来讲,局部变量在多线程环境中是线程安全的,因为每个线程都拥有自己独立的一份副本。 然而,实际的情况可能更为复杂。例如,如果局部变量引用了非线程安全的...

    Java中堆内存与栈内存分配浅析

    - **栈内存**:固定分配,大小在编译时确定,用于存储局部变量和方法调用信息。 ##### 2. 生命周期的比较 - **堆内存**:对象的生命周期不确定,由垃圾回收器决定何时回收。 - **栈内存**:变量的生命周期与方法的...

    慢慢的回味.entry_point–JVM Java栈桢的创建1

    每个方法都对应一个栈桢,栈桢包含了方法的局部变量、操作数栈、方法返回地址等信息。在Java程序执行过程中,JVM会根据方法的调用关系创建和销毁栈桢。 二、栈桢的结构 栈桢的结构可以分为以下几个部分: * 局部...

    关于Java栈与堆的思考

    栈是一种先进后出(LIFO,Last In First Out)的数据结构,主要用于存储方法调用时的信息,如局部变量、操作数栈、动态链接、方法出口等。Java中的栈具有以下特点: - **速度快**:栈的存取速度仅次于CPU寄存器,...

    函数如何调用:出入Java栈1

    总的来说,Java函数调用涉及到内存的多个层次,包括堆上的对象分配、栈上的局部变量和操作数管理,以及帧数据区的组织。理解这些机制对于优化代码、排查问题以及提升程序性能至关重要。在实际开发中,熟练掌握这些...

    Java中的堆和栈

    每当程序执行到一个方法时,Java虚拟机会为这个方法分配一块新的栈帧,用于存储该方法内的所有局部变量。这些局部变量包括基本数据类型(如`int`、`double`等)以及对象的引用。 ##### 特点 - **作用域限定**:栈...

    Java 中的堆和栈

    当在代码中声明一个局部变量时,Java会在栈中为其分配空间。一旦变量超出其作用域,Java会自动释放相应的内存空间,以便其他变量使用。栈内存的存取速度非常快,仅次于CPU的寄存器,因为它的操作是线性的,不需要像...

    Java卡Java卡虚拟机解释器Java栈异常处理[定义].pdf

    在Java卡虚拟机中,Java栈用于存储计算过程中的局部变量和操作数。每个方法调用都会在Java栈上创建一个栈帧,包含方法的局部变量、操作数、返回地址等信息。Java栈的管理是解释器的重要职责,包括栈帧的分配、数据的...

    Java中堆内存和栈内存详解

    每当调用一个方法时,都会在栈上创建一个新的栈帧来保存该方法的信息,如局部变量、参数和返回地址等。 - **堆空间**:堆是所有线程共享的一块内存区域,用于存储对象的实例。JVM通过垃圾回收机制自动管理堆内存,...

    堆和栈总结

    ### 堆和栈总结 #### 一、堆栈概念概览 在计算机科学中,堆和栈是非常重要的数据结构,它们在...通过熟悉栈帧的结构、局部变量区的特点以及操作数栈的工作方式,开发者能够更好地优化代码,提高程序的效率和稳定性。

    02.Java虚拟机栈1

    在Java程序执行过程中,每当一个方法被调用时,都会在虚拟机栈中创建一个对应的栈帧,用于存储局部变量、操作数、动态链接、方法出口等信息。这个过程与方法的调用和返回紧密相关,栈帧的入栈和出栈顺序反映了方法...

    java 队列 链表 栈

    栈则常用于函数调用,每次函数调用都会创建一个新的栈帧,保存局部变量和返回地址,当函数返回时,对应的栈帧会被弹出。 总的来说,理解和熟练运用Java中的队列、链表和栈对于编写高效的代码至关重要。通过深入学习...

    深入理解JVM-java虚拟机栈.docx

    栈的主要任务是为每个方法的执行提供一个栈帧(Stack Frame),栈帧存储了方法执行过程中的局部变量、操作数栈、动态连接和方法返回地址等关键信息。 栈帧是虚拟机栈的元素,它包含了以下几个重要组成部分: 1. ...

    java栈与堆1

    栈内存主要负责存储程序运行过程中的局部变量,包括基本类型变量(如int、char)和对象的引用变量。在Java中,当函数执行时,这些变量会被分配到栈内存中。栈内存具有快速存取的特点,因为它的数据结构类似于一个...

    Java虚拟机栈--栈帧.docx

    1. **局部变量表** (Local Variables):局部变量表是一个用于存储方法参数和局部变量的数字数组。数组中的每个元素被称为变量槽(Slot)。局部变量表的大小在编译时期就已经确定,并记录在方法的Code属性中。变量槽...

    栈的java版演示栈的java版演示栈的java版演示

    - **函数调用**:每个函数调用都会在内存中创建一个栈帧,存储局部变量和返回地址,当函数执行完毕,对应的栈帧会被弹出。 4. **自定义栈实现** 虽然`java.util.Stack`提供了栈的功能,但有时我们可能需要更灵活...

Global site tag (gtag.js) - Google Analytics