Java编译与反编译

admin5个月前笔记37
基本概念

我们可以通过javac命令将Java程序的源代码编译成Java字节码,即我们常说的class文件,这是我们通常意义上理解的编译。但是,字节码并不是机器语言,要想让机器能够执行,还需要把字节码翻译成机器指令,这个过程是通过解释器实现的,叫解释执行。注意:大家别把编译和解释执行混淆了,而后面所说的后端编译过程是JVM为提高效率做的优化,在不同的虚拟机实现中,执行引擎在执行字节码的时候,通常会有解释执行(通过解释器执行)和编译执行(通过即时编译器产生本地代码执行)两种选择,也可能两者兼备。所以大家可以思考下,Java到底是属于编译型语言还是解释器语言呢?那为什么java不直接编译成可执行文件呢,其实主要还是为了实现跨平台。Java源码通过编译成字节码,然后通过不同平台的虚拟机解释执行,从而实现一次编译,到处运行的跨平台的效果。

编译原理

Java语言的编译期分为前端编译和后端编译两个阶段

前端编译

前端编译是指把*.java文件转变成*.class文件的过程,包括词法分析、语法分析、语义分析与中间代码生成。

主要有下面几个步骤:

image.png

后端编译

在部分商用虚拟机中,Java程序最初是通过解释器进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为热点代码

为了提高热点代码的执行效率,在运行时, 虚拟机将会把这些代码编译成与本地平台相关的机器码

完成这个任务的后端编译器称为即时编译器(JIT编译器)

反编译
什么是反编译

既然Java 编译是指将 Java 源码编译成 Java 字节码的过程

那么Java 反编译简单说就是指根据 Java 字节码翻译成源码的过程

为什么要有反编译

首先这个源码是字符编码,字节码是二进制字节流,并且源码是给人看的,字节码是给虚拟机看的

因此如果想给人看,需要将字节码转为源码。如果想给虚拟机执行,需要将源码编译成字节码,当我们有类文件想看源码时,可以采用反编译的方式实现

比如想了解某个Java 语法糖编译后,再反编译是什么样的;别人给你发一个 jar 包,你需要看其中某个类是怎么写的,等此类情况都可以考虑是用 Java 反编译

反编译工具
JD-GUI

GitHub :https://github.com/java-decompiler/jd-gui

官网:http://java-decompiler.github.io/

image.png

下载后将类文件或者 jar 包直接拖动到界面即可

Luyten

下载地址:https://github.com/deathmarine/Luyten/releases

Arthas

官网:https://arthas.aliyun.com/doc/

可以使用 jad 命令将 JVM 中运行的 class 的 byte code 反编译成 java 代码

javap

javap是jdk自带的一个工具,可以对代码反编译,也可以查看java编译器生成的字节码

直接通过javap -help查看其用法

用法: javap其中, 可能的选项包括: 
  -help  --help  -?        输出此用法消息 
  -version                 版本信息 
  -v  -verbose             输出附加信息 
  -l                       输出行号和本地变量表 
  -public                  仅显示公共类和成员 
  -protected               显示受保护的/公共类和成员 
  -package                 显示程序包/受保护的/公共类 
                           和成员 (默认) 
  -p  -private             显示所有类和成员 
  -c                       对代码进行反汇编 
  -s                       输出内部类型签名 
  -sysinfo                 显示正在处理的类的 
                           系统信息 (路径, 大小, 日期, MD5 散列) 
  -constants               显示最终常量 
  -classpath指定查找用户类文件的位置 
  -cp指定查找用户类文件的位置 
  -bootclasspath覆盖引导类文件的位置

基本使用:

javac Test.java 
javap -c Test.class
jclasslib

jclasslib 是一种可视化的字节码查看工具,可以直接在 IDEA 插件安装

安装以后,在 IDEA 编译源码后,可以选择 View” ->“Show Bytecode With Jclasslib即可查看字节码

可以直观地看到 class 文件包含基本信息、常量池、接口信息、字段信息、方法信息和属性信息

其中方法信息又包含行号表、局部变量表,异常表等

要读懂字节码指令涉及的知识很多,之后的文章会通过案例详细讲解class文件结构和字节码指令的执行过程

推荐两本非常经典的图书:《深入理解 Java 虚拟机》、《Java 虚拟机规范》

反编译示例

下面看一个简单和常见的案例:

public class ForEachDemo { 
    public static void main(String[] args) { 
 
        Listdata = new ArrayList<>(); 
        data.add("a"); 
        data.add("b"); 
 
        for (String str : data) { 
            System.out.println(str); 
        } 
 
    } 
}

我们直接在 IDEA 对该类文件进行编译,然后再 target 目录中寻找该类,双击打开,得到下面的反编译源码:

public class ForEachDemo { 
    public ForEachDemo() { 
    } 
 
    public static void main(String[] args) { 
        Listdata = new ArrayList(); 
        data.add("a"); 
        data.add("b"); 
        Iterator var2 = data.iterator(); 
 
        while(var2.hasNext()) { 
            String str = (String)var2.next(); 
            System.out.println(str); 
        } 
 
    } 
}

从上述反编译代码可以清楚地看到,原始代码中没有编写构造方法时,编译器会自动生成一个默认构造方法;foreach 循环来遍历 list 时,底层通过 iterator 来实现


相关文章

Xshell如何连接服务器

Xshell如何连接服务器

数字化时代,服务器的使用是比较普遍的。然而对于服务器的操作大多是采取远程方式控制的,因此各种远程终端成为大家常用的软件。在诸多终端中,有一款比较出色的软件,就是Xshell。也许很多朋友们并不是很了解...

Linux下搭建FTP服务器教程(vsftp)

Linux下搭建FTP服务器教程(vsftp)

一、基本安装1. 运行以下命令安装 vsftpd。 yum install -y vsftpd2.运行以下命令打开及查看etc/vsftpdcd /etc/vsftpd说明:/et...

勒索病毒下数据安全的反思

勒索病毒下数据安全的反思

互联网时代的蓬勃发展,带来的便利和未来的期待的超越想象,同时也不可避免的增加了个人资料个人隐私泄密的风险。这次的勒索病毒事件,同时也曝露了数据安全的重要性,全球陷入恐慌中。而路透也援引数据称,勒索病毒...

Linux系统中设置开机自动运行的两种方法

Linux系统中设置开机自动运行的两种方法

有时可能会需要在重启时或者每次系统启动时运行某些命令或者脚本。我们要怎样做呢?本文中我们就对此进行讨论。 我们会用两种方法来描述如何在 CentOS/RHEL 以及 Ubuntu 系统上做到...

Docker与DevOps的结合:实现自动化监控和日志管理

Docker与DevOps的结合:实现自动化监控和日志管理

1.引言1.1 概念和背景软件开发和运维领域,Docker和DevOps是两个备受关注的重要概念。了解这两个概念的背景和意义对于理解如何将它们结合起来实现自动化、监控和日志管理至关重要。Docker的...

网络端口地址转换 NAPT 配置

网络端口地址转换 NAPT 配置

实验目的理解 NAT 网络地址转换的原理及功能掌握 NAPT 的配置,实现局域网访问互联网实验背景你是某公司的网络管理员,公司办公网需要接入互联网,公司只向 ISP 申请了一条专线,该专线分配了一个公...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。