`

使用类分解器Javap分析Java字节码

    博客分类:
  • Java
阅读更多

一直在学习Java,碰到了很多问题,碰到了很多关于i++和++i的难题,以及最经典的String str = "abc" 共创建了几个对象的疑难杂症。 知道有一日知道了java的反汇编 命令  javap。现将学习记录做一小结,以供自己以后翻看。如果有错误的地方,请指正

1.javap是什么:

 where options include:
-c Disassemble the code
-classpath <pathlist> Specify where to find user class files
-extdirs <dirs> Override location of installed extensions
-help Print this usage message
-J<flag> Pass <flag> directly to the runtime system
-l Print line number and local variable tables
-public Show only public classes and members
-protected Show protected/public classes and members
-package Show package/protected/public classes
and members (default)
-private Show all classes and members
-s Print internal type signatures
-bootclasspath <pathlist> Override location of class files loaded
by the bootstrap class loader
-verbose Print stack size, number of locals and args for met
hods
If verifying, print reasons for failure 

以上为百度百科里对它的描述,只是介绍了javap的一些参数和使用方法,而我们要用的就是这一个:-c Disassemble the code。

明确一个问题:javap是什么?网上有人称之为 反汇编器,可以查看java编译器为我们生成的字节码。通过它,我们可以对照源代码和字节码,从而了解很多编译器内部的工作。

2.初步认识javap

从一个最简单的例子开始:

 

 这个例子中,我们只是简单的声明了两个int型变量并赋上初值。下面我们看看javap给我们带来了什么:(当然执行javap命令前,你得首先配置好自己的环境,能用javac编译通过了,即:javac TestJavap.java )

我们只看(方便起见,将注释写到每句后面)

  Code:
   0:   iconst_2
    //把2放到栈顶
   1:   istore_1    //把栈顶的值放到局部变量1中,即i中
   2:   iconst_3    //把3放到栈顶
   3:   istore_2    //把栈顶的值放到局部变量1中,即j中
   4:   return

是不是很简单?(当然,估计需要点数据结构的知识) ,那我们就补点java的关于堆栈的知识:

对于 int i = 2;首先它会在栈中创建一个变量为i的引用,然后查找有没有字面值为2的地址,没找到,就开辟一个存放2这个字面值的地址,然后将i指向2的地址。

看了这段话,再比较下上面的注释,是不是完全吻合?

为了验证上面这一说法,我们继续实验:

我们将 i 和 j的值都设为2。按照以上理论,在声明j的时候,会去栈中招有没有字面值为2的地址,由于在栈中已经有2这个字面值,便将j直接指向2的地址。这样,就出现了i与j同时均指向2的情况。

 拿出javap -c进行反编译:结果如下:

  Code:
   0:   iconst_2    //把2放到栈顶
   1:   istore_1    //把栈顶的值放到局部变量1中,即i中
   2:   iconst_2    //把2放到栈顶
   3:   istore_2    //把栈顶的值放到局部变量2中,即j中(i 和 j同时指向2)
   4:   return

虽然这里说i和j同时指向2,但这里不等于说i和j指向同一块地址(java是不允许程序员直接修改堆栈中的数据的,所以就不要想着,我是不是可以修改栈中的2,那样岂不是i和j的值都会变化。另:在编译器内部,遇到j=2;时,它就会重新搜索栈中是否有2的字面值,如果没有,重新开辟地址存放2的值;如果已经有了,则直接将j指向这个地址。因此,就算j另被赋值为其他值,如j=4,j值的改变不会影响到i的值。)

再来一个例子:

还是javap -c

  Code:
   0:   iconst_2    //把2放到栈顶
   1:   istore_1    //把栈顶的值放到局部变量1中,即i中
   2:   iload_1     //把i的值放到栈顶,也就是说此时栈顶的值是2
   3:   istore_2    //把栈顶的值放到局部变量2中,即j中
   4:   return

看到这里是不是有点明确了?

 

既然我们对javap有了一定的了解,那我们就开始用它来解决一些实际的问题:

1.i++和++i的问题

反编译结果为

 Code:
  0:   iconst_1
  1:   istore_1
  2:   iinc    1, 1 //这个个指令,把局部变量1,也就是i,增加1,这个指令不会导致栈的变化,i此时变成2了
  5:   iconst_1
  6:   istore_2
  7:   iinc    2, 1//这个个指令,把局部变量2,也就是j,增加1,这个指令不会导致栈的变化,j此时变成2了
  10:  return

 

可以看出,++在前在后,在这段代码中,没有任何不同。

我们再看另一段代码:

反编译结果:

  Code:
   0:   iconst_1
   1:   istore_1
   2:   iload_1
   3:   iinc    1, 1  //局部变量1(即i)加1变为2,注意这时栈中仍然是1,没有改变
   6:   istore_1    //把栈顶的值放到局部变量1中,即i这时候由2变成了1
   7:   iconst_1
   8:   istore_2
   9:   iinc    2, 1 //局部变量2(即j)加1变为2,注意这时栈中仍然是1,没有改变
   12:  iload_2    //把局部变量2(即j)的值放到栈顶,此时栈顶的值变为2
   13:  istore_2   //把栈顶的值放到局部变量2中,即j这时候真正由1变成了2
   14:  return

是否看明白了? 如果这个看明白了,那么下面的一个问题应该就是迎刃而解了:

m = m ++;这句话,java虚拟机执行时是这样的: m的值加了1,但这是栈中的值还是0, 马上栈中的值覆盖了m,即m变成0,因此不管循环多少次,m都等于0。

如果改为m = ++m; 程序运行结果就是100了。。。

转自:http://blog.csdn.net/luckyp/archive/2009/06/09/4255353.aspx

另附上JVM的命令集

 

 

分享到:
评论
2 楼 lihu 2012-02-17  
分析的非常好,学习了!
1 楼 libo_591 2010-09-14  
分析的非常精彩,逻辑非常清晰

相关推荐

    JAVA字节码JAVA字节码.doc

    一、Java 类分解器 —— javap javap 是 JDK 中的一个命令行工具,用于将 Java 字节码反编译成可读的格式。javap 可以将类文件(.class)中的字节码反编译成 Java 源代码的形式,打印出类中的公共域、方法、构造...

    java虚拟机源码-jvm_based_compiler:该程序实现了递归下降解析器,将源代码转换为字节码,以便生成的字节码可以在Java虚拟

    在本文中,我们将深入探讨一个基于JVM的编译器项目,该编译器使用递归下降解析器将源代码转换为Java字节码。这个开源项目对于理解编译器工作原理和JVM内部机制具有很高的学习价值。 首先,让我们了解一下递归下降...

    第2章+Java运行环境讲义.pptx

    - **分解器(javap)**:反汇编Java字节码,展示类的内部结构。 了解并掌握这些知识点,对于学习和开发Java程序至关重要。在实际操作中,配置好JDK环境并熟悉其工具的使用,能有效提升开发效率。同时,理解Java运行...

    JAVA程序设计习题库及答案(非常全面)

    java类分解器 **解析:** javac.exe 是Java语言编译器,用于将Java源代码编译成字节码(.class文件)。 8. **题目:** java的API结构中,不属于类库主要包括的核心包的是 - A. java包 - B. javax - C. javadoc...

    java习题及答案(共11章).doc

    - JDK(Java Development Kit)包含了开发Java程序所需的工具,如javac.exe(Java编译器)、java.exe(Java解释器)、javadoc.exe(文档生成器)和javap.exe(类分解器)等。 4. **Java程序结构**: - 每个Java...

    Java的运行系统与程序编写.ppt

    分解器(`javap.exe`)则可以展示编译后的字节码信息,方便理解类和方法的内部结构。 JavaScript,虽然名字相似,但与Java是两种不同的语言。JavaScript主要用于Web前端开发,实现动态交互效果和服务器端通信。它...

    java程序设计教程复习资料

    - JDK工具中,javac.exe是Java语言编译器,java.exe是字节码解释器,javadoc.exe是文档生成器,javap.exe是类分解器。 7. **API和类库**: - 核心包不包括javadoc包,主要包有java、javax和org扩展包。 - 每个...

    Java习题库与答案

    7. **JDK工具**:`javac.exe`是Java语言编译器,`java.exe`是字节码解释器,`javadoc.exe`是文档生成器,`javap.exe`是类分解器。 8. **API结构**:Java的核心包包括java、javax,但不包括javadoc包,`org`是扩展包...

    面向对象程序设计总复习.pptx

    3. 运行Java程序:使用Java解释器(java.exe)来解释执行字节码文件。 四、简单的JAVA应用程序 一个简单的JAVA应用程序包括源文件的编写与保存、编译和运行三个步骤。 1. 源文件的编写与保存:源文件是由若干个...

    Java代码的编译与反编译

    Java字节码设计用于Java虚拟机(JVM),使得Java程序具备了平台无关性。这意味着Java编译后的字节码可以在任何安装了JVM的平台上运行,不必像C或C++那样针对不同的平台编译生成不同的可执行文件。 三、反编译过程 ...

    java复习内容1.pdf

    javap.exe是Java类分解器,可以反编译查看字节码。 【数据类型】Java中有两种数据类型:基本数据类型和引用数据类型。基本数据类型包括整数类型(如int)、浮点数类型(如float)、布尔类型(boolean)以及字符类型...

    java 复习题

    Java解释器使用字节码作为平台无关的指令集,使得Java程序可以在任何支持Java虚拟机的平台上运行。 **20. 移植接口** - **答案**:移植接口。Java体系结构中最下层是移植接口,它保证了Java体系结构可以在不同平台...

    java复习习题.pdf

    `javadoc`用于生成API文档,而`javap`是类分解器,用于查看类文件的内部结构。 4. **数组定义**:在Java中,数组的定义和初始化有多种方式。选项A定义了一个未初始化的整型数组,而B、C和D都是正确的初始化方式,但...

    1609第一次月考详细解析.doc

    B是Java字节码解释器(`java.exe`),C是Java文档生成器(`javadoc.exe`),D是Java类分解器(`javap.exe`)。 8. **数组操作**: - 这部分代码展示了如何合并两个数组到一个新的数组`threeArr`中。它使用了一个...

    Windows7中JDK配置方法

    5. **分解器(javap.exe)**:分析字节码并展示类的相关信息,如方法和变量。 6. **文档生成器(javadoc.exe)**:从源代码生成HTML格式的API文档。 这些工具是Java开发的基础,理解并熟练使用它们能极大地提高开发...

    2022山东计算机等级考试考试考前冲刺卷(2).docx

    7. **Java工具**:Java 类分解器是C.javap.exe,它可以反汇编.class文件,显示字节码和相关的符号信息。 8. **数据库操作**:在给定的选项中,表达式不合法的是A.新建一个数据库,因为这看起来像是SQL语句的一...

    Compiladores:编译器

    开发者可以利用编译器提供的工具,如javap(反汇编器)来查看生成的字节码,帮助理解程序的运行机制。 此外,Java编译器也支持一些特性,如泛型、异常处理、接口和多线程等,这些都是Java语言的强大之处。通过深入...

    learn_compiler

    字节码的解释和优化由JVM负责,通过类加载器动态加载类,并使用即时编译器(JIT)将部分字节码编译为本地机器码,以提升性能。 在"learn_compiler-master"这个项目中,你可能会遇到实际编译器开发的工具和框架,...

Global site tag (gtag.js) - Google Analytics