精华内容
下载资源
问答
  • 在上一篇文章《StringBuilder、StringBuffer与Java字符串处理》中,我们反汇编了Java字节码文件,通过查看编译器编译后的字节命令,我们能够更清楚地了解Java在字符串拼接等方面的处理机制。 那么,我们如何反...

    在上一篇文章《StringBuilder、StringBuffer与Java字符串处理》中,我们反汇编了Java字节码文件,通过查看编译器编译后的字节命令,我们能够更清楚地了解Java在字符串拼接等方面的处理机制。

    那么,我们如何反编译指定的Java字节码文件呢?其实,在Sun公司提供的JDK中,就已经内置了Java字节码文件反编译工具javap.exe(位于JDK安装目录的bin文件夹下)。

    我们可以在dos窗口中使用javap来反汇编指定的Java字节码文件。在使用javap的相关dos命令之前,你必须确保已经将JDK安装目录\bin添加到环境变量path中。

    接着,我们就可以使用javap来反编译指定的Java字节码文件了。在此之前,我们先通过javap的帮助命令javap -help查看javap相关指令的用法。

    javap-help

    从上述内容我们可以知道,javap的使用命令格式为javap 选项参数 类名,其中选项参数可以有多个,中间用空格隔开,也可以一个都没有。下面我们编写如下源代码文件(包名test,类名Person),并将其编译为Person.class字节码文件。

    1. package test;public class Person {
    2.     public Person(String name, int age, boolean gender, String address) {
    3.         this.name = name;
    4.         this.age = age;
    5.         this.gender = gender;
    6.         this.address = address;
    7.     }
    8.     private String name; // private修饰符
    9.     int age; // 默认无访问修饰符(即下面所说的package、friendly)
    10.     protected boolean gender; // protected修饰符
    11.     public String address; // public修饰符
    12.     public String getName() {
    13.         return name;
    14.     }
    15.     public void setName(String name) {
    16.         this.name = name;
    17.     }
    18.     public void sayHi() {
    19.         System.out.println("Hello, my name is " + this.name);
    20.     }
    21. }

    接着将包名文件夹test及Person.class放置在D:\java目录下。以便于我们使用javap命令进行测试。

    java-person-class

    在执行命令之前,我们需要将dos窗口的当前工作目录变更为D:\java\test

    cd-current-dir

    1、使用不带任何选项参数的命令:javap Person

    javap-person

    javap Personjavap -package Person的显示结果一样,因为-package选项参数是默认的,用于显示package(不带任何访问修饰符,即我们常说的friendly)、protectedpublic修饰的类或成员。

    备注:在dos下进入工作目录D:\java,然后使用命令javap test.Person也可以实现上述操作。下同。

    2、使用命令:javap -public Person显示public修饰的类或成员。

    javap-public-person

    与此类似,选项参数-protected用于显示protected以上访问级别(protectedpublic)的类或成员;选项参数-private用于显示private以上访问级别,也就是所有的类或成员。

    3、使用命令:javap -public -l Person显示public修饰的类或成员,并显示行号表格和本地变量表格。

    javap-public-l-person

    4、使用命令:javap -c Person显示Person.class反汇编出的字节码命令。

    javap-c-person

    由于选项参数之间组合较多,因此其他选项参数不再一一截图赘述,仅在下面使用文字进行说明:

    -classpath <pathlist>
    手动指定用户class字节码文件的存放目录,javap程序将在此目录下查找class文件,多个路径以英文分号分隔。例如:javap -classpath D:\java\test Person(即使DOS窗口的当前工作目录为其他任意路径,该命令均可正确执行)。
    -s
    打印变量的内部类型签名,例如:javap -classpath D:\java\test -s Person。
    -extdirs <dirs>
    指定javap搜索已安装的java扩展的位置,默认的java扩展的位置为jre\lib\ext。例如:javap -classpath D:\java\test -extdirs D:\java\myext Person
    -bootclasspath <pathlist>
    指定使用Java底层类加载器(bootstrap class loader)加载的字节码文件的位置。例如:javap -classpath D:\java\test -bootclasspath D:\java\core Person
    -verbose
    打印方法参数和本地变量的数量以及栈区大小。
    -J<flag>
    使用javap.exe来执行java.exe虚拟机的相关命令,例如javap -J-version相当于java -version,可以有多个命令,中间以空格隔开。
    展开全文
  • 本文主要介绍了介绍了Java中的一些基础知识点以及Java中的字节码。重点讲述了如何编译Java代码并查看字节码文件,并实际分析了一段字节码文件,便于更好的理解Java的字节码。

    Java基本概念

    Java 是一种面向对象静态类型编译执行,有VM/GC运行时跨平台高级语言

    面向对象

    面向对象应该是在接触Java时就会谈到的一个特性,因此很多人都有自己的解释。我的理解就是,面向对象就是一种数据的封装方式,是一种编程方式。

    静态类型

    经常会听到静态语言和动态语言的说法。简单来说,可以这么理解:静态类型语言中,变量的类型必须先声明,即在创建的那一刻就已经确定好变量的类型,而后的使用中,你只能将这一指定类型的数据赋值给变量。如果强行将其他不相干类型的数据赋值给它,就会引发错误。而动态的编程语言则没这个问题,变量的类型不是固定的,可以自由转变。

    常见的动态类型的语言有:PHP、Ruby、Python
    静态类型的语言:C、C++、JAVA、C#

    可以看一张对比图:
    Java哪怕是用了var类型的变量,一旦给a赋值以后,它的类型就确定了,不允许后面再进行更改了。但是Pytho中的变量则没有这个问题,可以随便赋值。
    在这里插入图片描述

    运行时

    什么是运行时

    Java的运行时称之为Java Runtime,具体 Runtime 是个什么东西呢,就是说一个程序要在一个硬件或者平台上跑,就必须要有一个中间层用来把程序语言转换为机器能听懂的机器语言。

    我们写好了一段程序代码,这段代码计算机实际上是读不懂的,为了让机器能读懂并运行这段代码,就需要一个 Java 语言的运行时环境,只有在这个环境中计算机才能读懂它,计算机才能与这段代码打交道。

    我们写的这几句代码,表面上只有这么几句,但实际上Java要加载很多其它的依赖才能保证这段程序代码能顺利执行,在我们写代码的时候是不会关注这些内容的,这些东西Java会在运行时在为我们加入。
    在这里插入图片描述
    简单来说,JRE(Java Runtime Environment)就是Java的运行时,JRE中包含了虚拟机和相关的库等资源。可以说运行时提供了程序运行的基本环境,JVM在启动时需要加载所有运行时的核心库等资源,然后再加载我们的应用程序字节码,才能让应用程序字节码运行在JVM这个容器里。

    但也有一些语言是没有虚拟机的,编译打包时就把依赖的核心库和其他特性支持,一起静态打包或动态链接到程序中,比如Golang和Rust,C#等。这样运行时就和程序指令组合在一起,成为了一个完整的应用程序,好处就是不需要虚拟机环境,坏处是编译后的二进制文件没法直接跨平台了。由于将程序的运行环境一起打包进了程序中,在Windows上编译的程序只包含与Windows有关的运行环境,因此,在Windows上编译的程序只能在Windows上运行,在Linux上编译的程序只能在Linux上执行。每到一个新的环境中,都得重新编译一下程序,无法一次编译,到处运行。

    跨平台

    比如C++编译的代码后的代码无法跨平台使用,在Windows上编译的 程序只能在Window上运行,要在Linux上运行,则需要在Linux上重新进行编译。而Java则不管在哪个平台上编译,只要编译成了.class文件,可以在任何机器上运行,前提是该机器得安装上Java虚拟机。
    在这里插入图片描述

    字节码

    Java bytecode 由单字节(byte)的指令组成,理论上最多支持256 个操作。
    一个字节有8位,可以表示0000 0000 ~ 1111 1111,即0 ~ 255。如果每一个数字都代表一个操作,那么最多支持256个操作。
    实际上Java 只使用了200左右的操作码, 还有一些操作码则保留给调试操作。

    根据指令的性质,主要分为四个大类:

    1. 栈操作指令,包括与局部变量交互的指令
    2. 程序流程控制指令
    3. 对象操作指令,包括方法调用指令
      常用的方法调用的指令
      invokestatic,顾名思义,这个指令用于调用某个类的静态方法,这是方法调用指令中最
      快的一个。
      invokespecial, 用来调用构造函数,但也可以用于调用同一个类中的private 方法, 以及
      可见的超类方法。
      invokevirtual,如果是具体类型的目标对象,invokevirtual 用于调用公共,受保护和
      package 级的私有方法。
      invokeinterface,当通过接口引用来调用方法时,将会编译为invokeinterface 指令。
      invokedynamic,JDK7 新增加的指令,是实现“动态类型语言”(Dynamically Typed Language)支持而进行的升级改进,同时也是JDK8 以后支持lambda 表达式的实现基
      础。
    4. 算术运算以及类型转换指令

    由于Java的操作是基于栈的,所以字节码主要起着从栈中store和load变量的作用。

    编译java文件生成class文件并查看

    • 使用javac命令将.java文件编译成.class文件
    PS D:\dev\Java\java-traning\jvm-learning\src\main\java\bytecode> javac HelloByteCode.java
    
    • 使用javap -c命令查看.class文件

    javap是JDK自带的反汇编器,可以查看java编译器为我们生成的字节码。了解编译器内部工作

    PS D:\dev\Java\java-traning\jvm-learning\src\main\java\bytecode> javap -c HelloByteCode.class
    Compiled from "HelloByteCode.java"
    public class bytecode.HelloByteCode {
      public bytecode.HelloByteCode();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: new           #2                  // class bytecode/HelloByteCode
           3: dup
           4: invokespecial #3                  // Method "<init>":()V
           7: astore_1
           8: ldc           #4                  // String a
          10: astore_2
          11: aload_2
          12: invokedynamic #5,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
          17: astore_2
          18: return
    }
    PS D:\dev\Java\java-traning\jvm-learning\src\main\java\bytecode>
    

    HelloByteCode.java中的源代码如下:

    package bytecode;
    
    public class HelloByteCode {
      public static void main(String[] args) {
        HelloByteCode helloByteCode = new HelloByteCode();
        String str = "a";
        str = str + "b";
      }
    }
    

    javap命令输出的内容究竟代表什么意义呢?如下图所示:

    在这里插入图片描述
    在这里插入图片描述

    如果以十六进制的形式打开.class文件,里面则是下图所下内容,实际上就是一串二进制数字,不过为了方便表示,用十六进制表示而已。

    Java是用一个字节码来表示一系列操作,用两个十六进制的数就可以表示一个8位的二进制数。比如图中的0025,可以理解为是两个操作,分别是0x000x25。那0x00表示什么操作,0x25又表示什么操作呢?

    可以查看一下JVM的字节对照表,就可以知道这些数字究竟对照着什么操作了。网上有很多,比如这个链接:JVM字节对照表

    .class文件中的内容(用Sublime Text 3打开)
    在这里插入图片描述

    • javap -c -verbose指令能看到更多的内容

    相比javap -c命令查看到的内容多了一些头信息,多了常量池,行号等内容。

    major version 55对应着Java 11
    在这里插入图片描述
    若编译的时候再加上-g的参数,eg:javac -g HelloByteCode.java再使用javap -c -verbose命令查看时就能查看到本地变量表的信息。
    在这里插入图片描述
    我们来分析一下LocalVariableTable(本地变量表,这里的本地是指线程本身,也就是这个变量表是处于运行的线程中的,里面的变量只有这个线程才能访问。而比如常量池则不是线程独占的,是线程共享的):

    • start指明变量从哪里开始起作用
    • length不是指变量的长度,而是指该变量其作用的范围,比如变量args从第0行开始起作用,作用长度为19,也就是作用到第19行,这里的行不是指代码中的第几行,而是使指用javap -c命令时每个指令前面标注的顺序。比如args是从顺序0开始生效,长度为19,也就是生效到顺序为18,也就是return这里。
      在这里插入图片描述
    • slot的意思是插槽,除了long和double所有的类型在本地变量的数组中占用一个slot,long和double需要两个连续的slot,因为这两个类型为64位类型,一个插槽为32位,在某种意义上也看作是变量的一个序号,按顺序将变量插入插槽中排列起来,方便到时候用。
    • Name对应着代码中的三个变量:argshelloByteCodestr
      在这里插入图片描述
    • Signature表示该对象对应的类的一个签名
      如果是基本的数据类型呢?int 对应一个大写字母I,char对应一个大写字母C,依次类推。
      在这里插入图片描述

    分析一段代码的字节码

    源代码:

    package bytecode;
    
    public class StringOperation {
      public static void main(String[] args) {
        String a = "a";
        String b = "a";
        String c = new String("a");
        String d = "a" + "b";
        String e = "a" + b;
      }
    }
    

    在这里插入图片描述

    stack=3, locals=6, args_size=1
             0: ldc           #2                  // String a
             2: astore_1
             3: ldc           #2                  // String a
             5: astore_2
             6: new           #3                  // class java/lang/String
             9: dup
            10: ldc           #2                  // String a
            12: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
            15: astore_3
            16: ldc           #5                  // String ab
            18: astore        4
            20: aload_2
            21: invokedynamic #6,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
            26: astore        5
            28: return
    

    分析字节码

    • 0: ldc:将int,float或String型常量值从常量池中推送至栈顶。也就是说,我们以这种方法定义一个String变量:String a = "a";会从常量池中找"a"这个值,然后赋给字符串变量a。程序在编译的时候就会将类似的常量,包括字符串常量,数字类型常量等放入常量池。然后在程序执行的时候就会去常量池中是否有相应的值。

    • 2: astore_1:将栈顶引用型数值存入第二个本地变量。依次类推:astore_2则表示将栈顶引用型数值存入第三个本地变量。这样的写法只能写到astore_3,往后则需要这么写``astore 4。可能有点好奇,String a = “a”;不是代码中的第一句吗,为什么不是先存储这个变量,为什么是这个变量是第二个被存入的,第一个被存入的是哪个变量?答案是第一个参数就是传入的参数args`
      在这里插入图片描述

      我们可以在该方法的本地变量表中找到args这个变量

    在这里插入图片描述

    但是在一些非静态的变量方法,我们可能会发现,即便我们没有传入任何参数,代码中的第一个变量变量依然是第二个被存储到栈中的。

    比如下面这张图。

    在这里插入图片描述

    这是因为在存储f这个变量之前,我们存储了当前类的一个自引用this,我们可以在LocalVariableTable中查看到this这个变量。

    • 6: new:创建一个对象, 并将其引用引用值压入栈顶。为什么这里会发生创建对象的操作呢?因此在我们的代码中这样创建了一个字符串变量c:String c = new String("a");通过这种方式创建。的String变量,不仅会在常量池中存储相应的值,还会在堆中存储其对象。

    • 9: dup:复制栈顶数值并将复制值压入栈顶。为什么需要复制呢?我们这时候new了一个String类型的对象,该对象对应的引用会被放入栈顶,进行复制之后,又会放入一个相同的引用放入栈顶,那这不就是重复了吗?为什么要放两个?因为执行String c = new String("a");的时候不是执行了第6步new操作以后就已经完全创建好c这个对象了,还需要执行第12步的invokespecial来完成该对象的初始化操作,这就相当于是执行构造函数,但是我们知道构造函数是没有返回值的,执行完毕以后,该引用也跟着被弹出栈了。所以如果不在前面再复制一个c变量的话,执行完毕以后栈里就没有c这个变量了。

    • 12: invokespecial:调用超类构建方法, 实例初始化方法, 私有方法。12: invokespecial #4中的#4指向的是常量池中索引为#4的变量,常量池中索引为#4的变量其实是一个方法,相当于调用了String的初始化构造方法。

    Constant pool:
    	......
        #3 = Class              #29            // java/lang/String
        #4 = Methodref          #3.#30         // java/lang/String."<init>":(Ljava/lang/String;)V
        ......
        #9 = Utf8               <init>
        ......
        #30 = NameAndType       #9:#38         // "<init>":(Ljava/lang/String;)V
        ......
        #38 = Utf8               (Ljava/lang/String;)V
        ......
    
    • 16: ldc:这句代码是发生在c变量创建并完成以后。而此时我们应该要执行String d = "a" + "b";这句代码,但是我们发现,似乎并没有发生拼接操作,也就发生了ldc这一个从常量池中读取值到栈顶的操作。16: ldc #5这句中的#5在常量池中是这样的:#5 = String #31 // ab。在编译的时候,编译器遇到"a" + "b"这样常量值的拼接操作,会将其直接进行合并,然后作为"ab"这么一个整体放入常量池中,不会在代码执行的时候再发生拼接操作了。

    • 20: aload_2:将第三个引用类型本地变量推送至栈顶。我们要执行这句代码String e = "a" + b;首先需要读取出b的值,b也就是第三个变量。

    • 21: invokedynamic #6, 0:调用动态方法。由于这里要发生String e = "a" + b;这样的拼接操作,在Java9之后 ,String的拼接是调用了StringConcatFactory.makeConcatWithConstants方法进行字符串拼接优化;而Java 8则是通过转换为StringBuilder,使用StringBuilderappend方法来进行字符串拼接。接着说:为什么要调用方法进行拼接呢?因为我们使用的String字符串,本质上是一个对象,对象之间是没有四则运算的操作的,对于对象,我们能做的只能是调用对象的方法。因此,我们在用+进行字符串的拼接的时候,相当于是用了Java的语法糖(所谓的语法糖可以理解为是一种简写,目的是用更少的代码实现同样的功能),本质上还是调用了对象的相应的方法来进行操作。

    String是线程安全的,StringBuilder是线程不安全的,将String的拼接转换为StringBuilder的append操作怎么能保证线程安全吗?
    因为只有在方法中的局部变量里才会这么操作,我们首先要明白一点,之所以出现并发问题,是因为多个线程需要共享同一个变量。方法中的局部变量本质上是用完就完了的,本质上就不是共享的,不会造成所谓的并发问题,所以对方法里的局部变量使用StringBuilder的拼接操作,不会对String的线程安全造成影响。

    常量池中对应的内容

    Constant pool:
        #6 = InvokeDynamic      #0:#35         // #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
        ......
        #35 = NameAndType        #41:#42        // makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
        ......
        #41 = Utf8               makeConcatWithConstants
        #42 = Utf8               (Ljava/lang/String;)Ljava/lang/String;
    

    参考:极客时间Java训练营

    展开全文
  • 编译查看具体详情字节码 Descriptor<()V> ()说明没有入参,V是没有返回值 Access flags 权限 []这是默认的,如果是public static那么[]会换成public static 那个0,3,4的号就是指令地址或者偏移地址,PC...

    反编译查看具体详情字节码
    在这里插入图片描述
    javap -v 自带的编译命令
    stack 操作数栈 栈深度 也算是数字数组长度
    locals 局部变量表长度 也算是数组长度
    在这里插入图片描述

    jclasslib工具
    Descriptor<()V> ()说明没有入参,V是没有返回值
    Access flags 权限 []这是默认的,如果是public static那么[]会换成public static
    在这里插入图片描述
    那个0,3,4的号就是指令地址或者偏移地址,PC寄存器存着这些地址,由执行引擎通过地址获取到后面的指令,比如lde,而执行引擎会操作局部变量表,操作数栈来进行一系列操作
    在这里插入图片描述
    第一列会放进PC寄存器又叫程序计数器里 第二列具体字节码指令 第三列符号引用 解析后指向常量池具体引用 在栈帧中叫动态链接
    在这里插入图片描述
    Maximum local variables 空间大小 最基本的存储单元slot(变量槽)(字)32位以下占一个, 除了long double因为是64位占俩个变量槽 其余一个变量槽(包含returnAddress类型)
    Code lenght 25 表示有25条指令,上面的ByteCode就是0-24 就是25条指令了
    在这里插入图片描述
    LineNumberTable就是Java代码的行号和字节码指令行号的对应关系,
    java代码的45行就是对应的字节码指令指令地址0
    java代码的46行就是对应的字节码指令指令地址10
    在这里插入图片描述

    局部变量表是一个数字数组,查看LocalVariableTable
    Descriptor L开头说明是引用,Name是变量名,index是数字数组的索引
    Start PC和lenght就是指明作用域范围,String s作用域是指令地址是10 有效长度15 也就是说它的作用域就是10+15 总指令行数是25 也就是它从指令地址第10开始可以被使用,根据上面LineNumberTable的关系也就是java从第46行,作用域到最后一行,也就是声明new String的下一行作用到最后一行
    在这里插入图片描述

    展开全文
  • java字节码文件编译

    2018-01-17 11:12:14
    jd-gui java字节码编译 class反编译 jd-gui java字节码编译 class反编译
  • javap 反编译 java 字节码文件

    千次阅读 2019-11-13 19:17:57
    javap是 Java class文件分解器,可以反编译,也可以查看java编译器生成的字节码,从而对代码内部的执行逻辑进行分析。 语法: 把java文件编译为class文件:javacTest.java(Test.javajava文件名) 生成对应的 ....

    概述:
             javap是 Java class文件分解器,可以反编译,也可以查看java编译器生成的字节码,从而对代码内部的执行逻辑进行分析。

    语法:
            把java文件编译为class文件:javac  Test.java  (Test.java为java文件名) 生成对应的 .class 文件 Test.class

            执行javap操作:javap 命令行 class文件名称(不加 .class后缀)

            例如: javap -c Test

    命令行
      -help 输出 javap 的帮助信息。
      -l 输出行及局部变量表。
      -b 确保与 JDK 1.1 javap 的向后兼容性。
      -public 只显示 public 类及成员。
      -protected 只显示 protected 和 public 类及成员。
      -package 只显示包、protected 和 public 类及成员。这是缺省设置。
      -private 显示所有类和成员。
      -J[flag] 直接将 flag 传给运行时系统。
      -s 输出内部类型签名。
      -c 输出类中各方法的未解析的代码,即构成 Java 字节码的指令。
      -verbose 输出堆栈大小、各方法的 locals 及 args 数,以及class文件的编译版本
      -classpath[路径] 指定 javap 用来查找类的路径。如果设置了该选项,则它将覆盖缺省值或 CLASSPATH 环境变量。目录用冒号分隔。
         - bootclasspath[路径] 指定加载自举类所用的路径。缺省情况下,自举类是实现核心 Java 平台的类,位于 jrelibt.jar 和 jrelibi18n.jar 中。
      -extdirs[dirs] 覆盖搜索安装方式扩展的位置。扩展的缺省位置是 jrelibext。
    示例:
    一个Demo.java文件(存放在桌面)

    class Demo 
    {
    	public static void main(String[] args) 
    	{
    		Integer aInteger = 56;
    		int aInt=0;
    		int aInt2 = 123;
    		String s="helloworld";
    		String aString = new String("IamString");
    	}
    }

    反汇编结果

    Compiled from "Demo.java"
    class Demo {
      Demo();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
     
      public static void main(java.lang.String[]);
        Code:
           0: bipush        56
           2: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
           5: astore_1
           6: iconst_0
           7: istore_2
           8: bipush        123
          10: istore_3
          11: ldc           #3                  // String helloworld
          13: astore        4
          15: new           #4                  // class java/lang/String
          18: dup
          19: ldc           #5                  // String IamString
          21: invokespecial #6                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
          24: astore        5
          26: return
    }

    对其中的语法不清楚啊?可以参照一下这两篇博客:

    javap -c 命令详解 http://blog.csdn.net/junsure2012/article/details/7099222

    JVM字节码之整型入栈指令(iconst、bipush、sipush、ldc) http://www.cnblogs.com/luyanliang/p/5498584.html

    如果还不清楚,放大招了:
    ORACLE 官方文档  Chapter 4. The class File Format  http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html
     

    常用反编译工具:

    1、jd-gui:最好用,但有时反编译出来的结果会有遗漏。

            https://code.google.com/p/cxldemo/downloads/detail?name=jd-gui.exe&can=2&q

    2、DJ Java Decompiler:相对jd-gui易用性上差一些,但是反编译过来的结果更准确。

            http://www.neshkov.com/dj.html

    3、jclasslib bytecode viewer:将字节码转化为JVM指令的工具。

            http://sourceforge.net/projects/jclasslib/

    展开全文
  • 深入理解java编译后的字节码文件

    千次阅读 2018-04-19 17:15:53
    从我们写的java文件到通过编译器编译成java字节码文件(也就是.class文件),这个过程是java编译过程;而我们的java虚拟机执行的就是字节码文件。不论该字节码文件来自何方,由哪种编译器编译...
  • 使用javap反编译Java字节码文件

    千次阅读 2016-06-23 09:17:31
    我们如何反编译指定的Java字节码文件呢?其实,在Sun公司提供的JDK中,就已经内置了Java字节码文件编译工具javap.exe(位于JDK安装目录的bin文件夹下)。 我们可以在dos窗口中使用javap来反汇编指定的Java字节码...
  • 编译字节码文件

    2019-11-26 19:56:57
    一个很酷的方法,来了解程序运行机制 javac test.java javap -c test.class >>a.txt //编译生成字节码文件 //反编译后写入名字为a的txt文件 现在大二了,我的学习之路开始了! ...
  • javap反编译java字节码文件

    千次阅读 2016-08-16 14:58:17
     javap是 Java class文件分解器,可以反编译,也可以查看java编译器生成的字节码,从而对代码内部的执行逻辑进行分析。 语法:  把java文件编译为class文件:javac Test.java (Test.javajava文件名) 生成对应...
  • 使用JavaCompile进行编译,代码很简单 ... * 编译Java文件 * * * @param path * 目录 */ public static void compileFile(List files) { try { JavaCompiler compiler = ToolProvider.getSystemJa
  • ***利用IDEA进行反编译字节码文件 java程序编译之后会生成一个class文件(字节码),我们可以通过Idea进行反编译。 过程:打开project structure->project->project compiler output(可以在下面看见一个地址,...
  • 怎么用java自带反编译工具查看java字节码文件图文教程,用java自带反编译工具查看java字节码文件,首先,配置好java开发环境,环境变量各种配置,这里就不一一说了,相信大家都配置好了。下面入正题----怎么用java...
  • 一、新建HelloWorld.java文件,内容如下(简易): public class HelloWorld { public int firstStack() { int a = 100; int b = 100; int c = 100; return (a+b)*c; } } 二、将后缀名为java的...
  • java习题 字节码文件

    2009-09-26 09:48:53
    Java语言》练习题 一,选择题: 1... Java源程序经编译生成的字节码文件的扩展名为 ,字节码文件1,阅读并理解Greetings.java,编写完成同样功能但在浏览器中运行的Applet应用程序GreetingsApplet.java和页面文件Greetings
  • 这个是Windows版本的jad反编译工具,可以方便地将java字节码文件.class反编译java文件
  • 如何解读JAVA编译的Class文件字节码) 首先我们编写一段简单的Java代码并编译 package Lab; public class ClassDemo { private int m; public int incM(){ return m+1; } } 编译后得到ClassDemo.class文件...
  • 自己一直使用的一款小工具:Java编译工具。 特点:小巧、绿色、易使用 作用:提高开发人员解决问题的效率,请大家按需下载。
  • java编译字节码

    2019-07-14 10:57:32
    class代码: package my; public class MyTest { public static void main(String[] args) { String a = "abc"; String r = a + "xyz" + "swq";...执行编译,生成MyTest.class文件: j...
  • 广州疯狂软件学院拥有三大... JAVA中通过编译时常量控制有的源代码不编译字节码文件  JAVA编译过程会对代码进行优化,如果某一行代码永远不可能被执行到,  这行代码不会被编译字节码文件中去。  如...
  • 我们在学习动态代理的实现原理时往往希望能够将字节码文件编译出来看一下代理类时如何调用handler的invoke方法来实现代理的,但是往往我们不知道如何下载字节码文件,或者下载来不知道下载路径,又或者使用javap反...
  • java编译字节码解析

    2016-12-29 14:14:00
    java编译字节码解析 参考网摘: https://my.oschina.net/indestiny/blog/194260 一、编译文件字节码解析 模数 u4 次版本号 u2 主版本号 u2 常量池 u2 类访问表示 u2 类名 u2 父类 u2 接口 u2 字段数目...
  • javap -c Atomicity ...---------- javap -c 产生的字节码文件---------- Compiled from "Atomicity.java" public class Atomicity { int i; public Atomicity(); Code: 0: aload_0 1: invok...
  • Java字节码文件

    千次阅读 2016-12-29 00:53:53
    编译器将Java源码编译成符合Java虚拟机规范的字节码文件。 字节码组成结构比较特殊,其内部不包含任何分隔符区分段落。 一组8位字节单位的字节流组成了一个完整的字节码文件。 字节码内部组成结构 《Java虚拟机规范 ...
  • 这行代码不会被编译字节码文件中去。 如下面的例子,flag是一个可以在编译阶段就可以确定的值, javac编译的时候不会把System.out.println编译字节码文件中。 public class T { public final static boolean...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,616
精华内容 5,046
关键字:

java编译字节码文件

java 订阅