热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【转】javap-c命令详解

javap-c命令详解一直在学习Java,碰到了很多问题,碰到了很多关于i++和++i的难题,以及最经典的Stringstrabc共创建了几个对象的疑难杂症。知道有一日知道

javap -c命令详解

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

1.javap是什么:

 

 where options include:
-c Disassemble the code
-classpath Specify where to find user class files
-extdirs Override location of installed extensions
-help Print this usage message
-J Pass 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 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了。。。


推荐阅读
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • 本文介绍了Java集合库的使用方法,包括如何方便地重复使用集合以及下溯造型的应用。通过使用集合库,可以方便地取用各种集合,并将其插入到自己的程序中。为了使集合能够重复使用,Java提供了一种通用类型,即Object类型。通过添加指向集合的对象句柄,可以实现对集合的重复使用。然而,由于集合只能容纳Object类型,当向集合中添加对象句柄时,会丢失其身份或标识信息。为了恢复其本来面貌,可以使用下溯造型。本文还介绍了Java 1.2集合库的特点和优势。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • 本文介绍了在Mac上安装Xamarin并使用Windows上的VS开发iOS app的方法,包括所需的安装环境和软件,以及使用Xamarin.iOS进行开发的步骤。通过这种方法,即使没有Mac或者安装苹果系统,程序员们也能轻松开发iOS app。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • Java如何导入和导出Excel文件的方法和步骤详解
    本文详细介绍了在SpringBoot中使用Java导入和导出Excel文件的方法和步骤,包括添加操作Excel的依赖、自定义注解等。文章还提供了示例代码,并将代码上传至GitHub供访问。 ... [详细]
  • 本文介绍了Java调用Windows下某些程序的方法,包括调用可执行程序和批处理命令。针对Java不支持直接调用批处理文件的问题,提供了一种将批处理文件转换为可执行文件的解决方案。介绍了使用Quick Batch File Compiler将批处理脚本编译为EXE文件,并通过Java调用可执行文件的方法。详细介绍了编译和反编译的步骤,以及调用方法的示例代码。 ... [详细]
  • CentOS 6.5安装VMware Tools及共享文件夹显示问题解决方法
    本文介绍了在CentOS 6.5上安装VMware Tools及解决共享文件夹显示问题的方法。包括清空CD/DVD使用的ISO镜像文件、创建挂载目录、改变光驱设备的读写权限等步骤。最后给出了拷贝解压VMware Tools的操作。 ... [详细]
  • 本文介绍了在CentOS上安装Python2.7.2的详细步骤,包括下载、解压、编译和安装等操作。同时提供了一些注意事项,以及测试安装是否成功的方法。 ... [详细]
  • ShiftLeft:将静态防护与运行时防护结合的持续性安全防护解决方案
    ShiftLeft公司是一家致力于将应用的静态防护和运行时防护与应用开发自动化工作流相结合以提升软件开发生命周期中的安全性的公司。传统的安全防护方式存在误报率高、人工成本高、耗时长等问题,而ShiftLeft提供的持续性安全防护解决方案能够解决这些问题。通过将下一代静态代码分析与应用开发自动化工作流中涉及的安全工具相结合,ShiftLeft帮助企业实现DevSecOps的安全部分,提供高效、准确的安全能力。 ... [详细]
author-avatar
freezing-wing
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有