前言
挺久没更文章了,之前有一个月在面试,后来写了篇面经,有一些朋友找我交流问题,所以一直没时间写技术文章,估计以后更新文章频率不会那么高了,不过还是会定期分享的,我的目的还是希望我的每篇文章大家都能学到点东西
基本概念
我们可以通过javac命令将Java程序的源代码编译成Java字节码,即我们常说的class文件,这是我们通常意义上理解的编译
但是,字节码并不是机器语言,要想让机器能够执行,还需要把字节码翻译成机器指令,这个过程是通过解释器实现的,叫解释执行
注意:大家别把编译和解释执行混淆了,而后面所说的后端编译过程是JVM为提高效率做的优化
在不同的虚拟机实现中,执行引擎在执行字节码的时候,通常会有解释执行(通过解释器执行)和编译执行(通过即时编译器产生本地代码执行)两种选择,也可能两者兼备
所以大家可以思考下,Java到底是属于编译型语言还是解释器语言呢
那为什么java不直接编译成可执行文件呢
为了实现跨平台
Java源码通过编译成字节码,然后通过不同平台的虚拟机解释执行,从而实现 一次编译,到处运行的跨平台的效果
编译原理
Java语言的编译期分为前端编译和后端编译两个阶段
前端编译
前端编译是指把*.java文件转变成*.class文件的过程
包括词法分析、语法分析、语义分析与中间代码生成
主要有下面几个步骤:
后端编译
在部分商用虚拟机中,Java程序最初是通过解释器进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为热点代码
为了提高热点代码的执行效率,在运行时, 虚拟机将会把这些代码编译成与本地平台相关的机器码
完成这个任务的后端编译器称为即时编译器(JIT编译器)
反编译
什么是反编译
既然Java 编译是指将 Java 源码编译成 Java 字节码的过程
那么Java 反编译简单说就是指根据 Java 字节码翻译成源码的过程
为什么要有反编译
首先这个源码是字符编码,字节码是二进制字节流,并且源码是给人看的,字节码是给虚拟机看的
因此如果想给人看,需要将字节码转为源码。如果想给虚拟机执行,需要将源码编译成字节码,当我们有类文件想看源码时,可以采用反编译的方式实现
比如想了解某个 Java 语法糖编译后,再反编译是什么样的;别人给你发一个 jar 包,你需要看其中某个类是怎么写的,等此类情况都可以考虑是用 Java 反编译
反编译工具
在线反编译工具
1.http://www.decompiler.com/
2.http://www.javadecompilers.com/,该网站的主要优势在于有多种反编译器可供选择
离线反编译工具
JD-GUI
GitHub :https://github.com/java-decompiler/jd-gui
官网:http://java-decompiler.github.io/
下载后将类文件或者 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 <options> <classes>
- 其中, 可能的选项包括:
- -help --help -? 输出此用法消息
- -version 版本信息
- -v -verbose 输出附加信息
- -l 输出行号和本地变量表
- -public 仅显示公共类和成员
- -protected 显示受保护的/公共类和成员
- -package 显示程序包/受保护的/公共类
- 和成员 (默认)
- -p -private 显示所有类和成员
- -c 对代码进行反汇编
- -s 输出内部类型签名
- -sysinfo 显示正在处理的类的
- 系统信息 (路径, 大小, 日期, MD5 散列)
- -constants 显示最终常量
- -classpath <path> 指定查找用户类文件的位置
- -cp <path> 指定查找用户类文件的位置
- -bootclasspath <path> 覆盖引导类文件的位置
基本使用:
- 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) {
- List<String> data = 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) {
- List<String> data = 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 来实现
本文转载自微信公众号「月伴飞鱼」,可以通过以下二维码关注。转载本文请联系月伴飞鱼公众号。
公司介绍 我们公司是全球法律服务整合平台,已有的4万多名律师遍布全国359个城市...
3月24日,腾讯发布2020年Q4及全年财报,其中金融科技及企业服务第四季收入385亿...
客户简介 趣医网(quyiyuan.com)创立于2014年,为京颐集团重要成员企业之一,是...
客户简介 全民直播是一家涵盖游戏、娱乐、户外等多领域泛娱乐的直播平台。2015年...
??提到慕尼黑,大家第一个想到总是啤酒节,其实慕尼黑的文化同样闻名世界。慕尼...
案例背景 高校健康打卡项目发起于北京大学软件与微电子学院,是该学院张齐勋老师...
云虚拟主机 可以干什么?云 虚拟主机 可以是搭 建网站 的重要产品,可用来存放网...
注册了 域名 不备案可以吗?可以的。 注册域名 并不是一定要备案的,只有搭 建网...
排查思路 无法通过远程桌面连接裸金属服务器时,我们推荐您按照以下思路排查问题...
API风格说明 当前ECS服务对外开放两类风格的API: ECS服务自定义规范的API(以下...