java中p表示什么意思_javap -c命令关键字的含义

java中p表示什么意思_javap -c命令关键字的含义jdk 提供了 javap 命令用于查看字节码来查看程序执行赋值的顺序 看懂这些关键字可以很好的理解程序执行的过程转自 http www cnblogs com duanxz archive 2014 05 14 3724426 html topJava 栈和局部变量操作 Java 虚拟机是基于栈的机器 几乎所有 Java 虚拟机的指令都与操作数栈相关 栈操作包括把常量压入操作数栈 执行通用的栈操作 在操作数

jdk提供了javap命令用于查看字节码来查看程序执行赋值的顺序,看懂这些关键字可以很好的理解程序执行的过程

转自:http://www.cnblogs.com/duanxz/archive/2014/05/14/3724426.html#top

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工具查看其字节码为:

Compiled from “StackTest.java”

public class StackTest extends java.lang.Object{

public StackTest();

Code:

0: aload_0

1: invokespecial #8; //Method java/lang/Object.””:()V

4: return

public static 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存入位置为7和8的局部变量中

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

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

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

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

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

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

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

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

37: return

}

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

将byte和short类型常量压入栈

操作码

操作数

说明

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虚拟机通过给定的索引查找相应的常量池入口,决定这些常量的类型和值,并把它们压入栈。

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

例如下面代码:

publicclassStackTest {

/

*@paramargs

*/

publicstaticvoidmain(String[] args) {

//TODOAuto-generated method stub

bytei = 125;

bytej = -128;

intk= i + j;

shorta = 32767;

shortb = – 32768;

intc= a + b;

intx = ;

inty = -;

intz= x + y;

longI = L;

longJ = -L;

longK= I + J;

}

}

用javap工具查看其字节码为:

Compiled from “StackTest.java”

public class StackTest extends java.lang.Object{

public StackTest();

Code:

0: aload_0

1: invokespecial #8; //Method java/lang/Object.””:()V

4: return

public static 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 //从常量池索引16的位置取出压入栈

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

59: return

}

2通用栈操作

操作码

操作数

说明

nop

(无)

不做任何操作

pop

(无)

从操作数栈弹出栈顶部的一个字

pop2

(无)

从操作数栈弹出最顶端的两个字

swap

(无)

交换栈顶部的两个字

dup

(无)

复制栈顶部的一个字

dup2

(无)

复制栈顶部的两个字

dup_x1

(无)

复制栈顶部的一个字,并将复制内容及原来弹出的两个字长的内容压入栈

dup_x2

(无)

复制栈顶部的一个字,并将复制内容及原来弹出的三个字长的内容压入栈

dup2_x1

(无)

复制栈顶部的两个字,并将复制内容及原来弹出的三个字长的内容压入栈

dup2_x2

(无)

复制栈顶部的两个字,并将复制内容及原来弹出的四个字长的内容压入栈

1,dup:复制栈顶部的一个字长的内容。

栈:

前:……,word

后:……,word,word

2,dup_x1:复制栈顶部一个字长的内容,然后将复制内容及原来弹出的两个字长的内容压入栈

栈:

前:……,word2,word1

后:……,word1,word2,word1

3,dup_x2:复制栈顶部一个字长的内容,然后将复制内容及原来弹出的三个字长的内容压入栈

栈:

前:…….,word3,word2,word1

后:…….,word1,word3,word2,word1

4,dup2:复制栈顶部长度为两个字长的内容

栈:

前:……,word2,word1

后:……,word2,word1,word2,word1

5,dup2_x1:复制栈顶部两个字长的内容,然后将复制内容及原来弹出的三个字长的内容压入栈

栈:

前:……,word3,word2,word1

后:…….,word2,word1,word3,word2,word1

6,dup2_x2:复制栈顶部两个字长的内容,然后将复制内容及原来弹出的四个字长的内容压入栈

栈:

前:……,word4,word3,word2,word1

后:…….,word2,word1,word4,word3,word2,word1

7,pop:弹出栈顶端一个字长的内容

栈:

前:……,word

后:…….

8,pop2:弹出栈顶端两个字长的内容

栈:

前:……,word2,word1

后:…….

9,swap:交换栈顶端两个字的内容

栈:

前:……,word2,word1

后:…….,word1,word2

例如如下代码:

publicclassStackTest {

/

*@paramargs

*/

publicstaticvoidmain(String[] args) {

//TODOAuto-generated method stub

String a;

String b;

a =newString(“aaa”);

b =newString(“aaa”);

}

}

用javap工具查看其字节码为:

Compiled from “StackTest.java”

public class StackTest extends java.lang.Object{

public StackTest();

Code:

0: aload_0

1: invokespecial #8; //Method java/lang/Object.””:()V

4: return

public static void main(java.lang.String[]);

Code:

0: new #16; //class java/lang/String

3: dup

4: ldc #18; //String aaa

6: invokespecial #20; //Method java/lang/String.””:(Ljava/lang/String;)V

9: astore_1

10: new #16; //class java/lang/String

13: dup

14: ldc #18; //String aaa

16: invokespecial #20; //Method java/lang/String.””:(Ljava/lang/String;)V

19: astore_2

20: return

}

3,把局部变量压入栈

将一个字长的局部变量压入栈

操作码

操作数

说明

iload

vindex

将位置为vindex的int类型的局部变量压入栈

iload_0

(无)

将位置为0的int类型的局部变量压入栈

iload_1

(无)

将位置为1的int类型的局部变量压入栈

iload_2

(无)

将位置为2的int类型的局部变量压入栈

iload_3

(无)

将位置为3的int类型的局部变量压入栈

fload

vindex

将位置为vindex的float类型的局部变量压入栈

fload_0

(无)

将位置为0的float类型的局部变量压入栈

fload_1

(无)

将位置为1的float类型的局部变量压入栈

fload_2

(无)

将位置为2的float类型的局部变量压入栈

fload_3

(无)

将位置为3的float类型的局部变量压入栈

将两个字长的局部变量压入栈

操作码

操作数

说明

lload

vindex

将位置为vindex和(vindex+1)的long类型的局部变量压入栈

lload_0

(无)

将位置为0和1的long类型的局部变量压入栈

lload_1

(无)

将位置为1和2的long类型的局部变量压入栈

lload_2

(无)

将位置为2和3的long类型的局部变量压入栈

lload_3

(无)

将位置为3和4的long类型的局部变量压入栈

dload

vindex

将位置为vindex和(vindex+1)的double类型的局部变量压入栈

dload_0

(无)

将位置为0和1的double类型的局部变量压入栈

dload_1

(无)

将位置为1和2的double类型的局部变量压入栈

dload_2

(无)

将位置为2和3double类型的局部变量压入栈

dload_3

(无)

将位置为3和4double类型的局部变量压入栈

将对象引用局部变量压入栈

操作码

操作数

说明

aload

vindex

将位置为vindex的对象引用局部变量压入栈

aload_0

(无)

将位置为0的对象引用局部变量压入栈

aload_1

(无)

将位置为1的对象引用局部变量压入栈

aload_2

(无)

将位置为2的对象引用局部变量压入栈

aload_3

(无)

将位置为3的对象引用局部变量压入栈

4,弹出栈顶元素,将其赋给局部变量

弹出一个字长的值,将其赋给局部变量

操作码

操作数

说明

istore

vindex

从栈中弹出int类型值,然后将其存到位置为vindex的局部变量中

istore_0

(无)

从栈中弹出int类型值,然后将其存到位置为0的局部变量中

istore_1

(无)

从栈中弹出int类型值,然后将其存到位置为1的局部变量中

istore_2

(无)

从栈中弹出int类型值,然后将其存到位置为2的局部变量中

istore_3

(无)

从栈中弹出int类型值,然后将其存到位置为3的局部变量中

fstore

vindex

从栈中弹出float类型值,然后将其存到位置为vindex的局部变量中

fstore_0

(无)

从栈中弹出float类型值,然后将其存到位置为0的局部变量中

fstore_1

(无)

从栈中弹出float类型值,然后将其存到位置为1的局部变量中

fstore_2

(无)

从栈中弹出float类型值,然后将其存到位置为2的局部变量中

fstore_3

(无)

从栈中弹出float类型值,然后将其存到位置为3的局部变量中

弹出对象引用,并将其赋值给局部变量

操作码

操作数

说明

lstore

vindex

从栈中弹出long类型值,然后将其存到位置为vindex和(vindex+1)的局部变量中

lstore_0

(无)

从栈中弹出long类型值,然后将其存到位置为0和1的局部变量中

lstore_1

(无)

从栈中弹出long类型值,然后将其存到位置为1和2的局部变量中

lstore_2

(无)

从栈中弹出long类型值,然后将其存到位置为2和3的局部变量中

lstore_3

(无)

从栈中弹出long类型值,然后将其存到位置为3和4的局部变量中

dstore

vindex

从栈中弹出double类型值,然后将其存到位置为vindex和(vindex+1)的局部变量中

dstore_0

(无)

从栈中弹出double类型值,然后将其存到位置为0和1的局部变量中

dstore_1

(无)

从栈中弹出double类型值,然后将其存到位置为1和2的局部变量中

dstore_2

(无)

从栈中弹出double类型值,然后将其存到位置为2和3的局部变量中

dstore_3

(无)

从栈中弹出double类型值,然后将其存到位置为3和4的局部变量中

操作码

操作数

说明

astore

vindex

从栈中弹出对象引用,然后将其存到位置为vindex的局部变量中

astore_0

(无)

从栈中弹出对象引用,然后将其存到位置为0的局部变量中

astore_1

(无)

从栈中弹出对象引用,然后将其存到位置为1的局部变量中

astore_2

(无)

从栈中弹出对象引用,然后将其存到位置为2的局部变量中

astore_3

(无)

从栈中弹出对象引用,然后将其存到位置为3的局部变量中

5,wide指令

无符号8位局部变量索引,把方法中局部变量数的限制在256以下。一条单独的wide指令可以将8位的索引再扩展8位,就可以把局部变量数的限制扩展到65536.

操作码

操作数

说明

wide

iload,index

从局部变量位置为index的地方取出int类型值,并将其压入栈

wide

lload ,index

从局部变量位置为index的地方取出long类型值,并将其压入栈

wide

fload,index

从局部变量位置为index的地方取出float类型值,并将其压入栈

wide

dload,index

从局部变量位置为index的地方取出double类型值,并将其压入栈

wide

aload,index

从局部变量位置为index的地方取出对象引用,并将其压入栈

wide

istore,index

从栈中弹出int类型值,将其存入位置为index的局部变量中

wide

lstore,index

从栈中弹出long类型值,将其存入位置为index的局部变量中

wide

fstore,index

从栈中弹出float类型值,将其存入位置为index的局部变量中

wide

dstore,index

从栈中弹出double类型值,将其存入位置为index的局部变量中

wide

astore,index

从栈中弹出对象引用,将其存入位置为index的局部变量中

跳转指令并不允许直接跳转到被wide指令修改过的操作码。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/179375.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午3:43
下一篇 2026年3月26日 下午3:44


相关推荐

  • OpenAI 正式发布AI智能体 ChatGPT Agent

    OpenAI 正式发布AI智能体 ChatGPT Agent

    2026年3月16日
    1
  • 1.1.2 三角形余弦定理

    1.1.2 三角形余弦定理含义 对于任意三角形 任何一边的平方等于其他两边平方的和减去这两边与它们夹角的余弦的积的两倍 几何意义 c 2 b cdotsin theta 2 a b cdotcos theta 2 b cdotsin theta 2 a 2 b cdotcos theta 2 2ab cdotcos

    2026年3月19日
    3
  • plsqldev8.0下载和注册码

    plsqldev8.0下载和注册码[b]关键词:PL/SQL,下载,plsqldev,注册码,plsqldev711,汉化文件[/b]PL/SQLDeveloper是一种集成的开发环境,专门用于开发、测试、调试和优化OraclePL/SQL存储程序单元,比如触发器等。PL/SQLDeveloper功能十分全面,大大缩短了程序员的开发周期。[url]http://www.kutoku.info/software…

    2022年4月25日
    47
  • freeradius ad认证(掉证书)

    http://blog.csdn.net/lassewang/article/details/9159543

    2022年4月12日
    58
  • redis是什么,为什么要用redis?

    redis是什么,为什么要用redis?Redis 的的是完全开源免费的 遵守 BSD 协议 是一个高性能的键值数据库 是当前最热门的的的 NoSql 数据库之一 也被人们称为数据结构服务器 那为什么要用 Redis 的的的呢 原因很简单 快 这个问题在大并发 高负载的网站中必须考虑 redis 数据库中的所有数据都存储在内存中 由于内存的读写速度远快于硬盘 因此 Redis 的的的在性能上对比其他基于硬盘存储的数据库有非常明显的优势 项目中使

    2026年3月18日
    2
  • mysql datetime格式化日期(mysql start with)

    *版权声明:本文为博主原创文章,转载请注明出处。*我们在日常数据统计时常会遇到“2018-12-1216:21:12”or“2018-12-1216:21:12.609000”这样的时间格式,假如要统计某一天产生了多少条数据量,SQL该怎么写呢?本文希望能够对大家学习和使用有所帮助。contentcreateTime设备2018-12-1015:20:20…

    2022年4月13日
    53

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号