跟随Javac代码来解答字节码的疑惑
前言
本文是跟随掘金小册张师傅的《JVM字节码从入门到精通》练习而写的。
问题
问题一:
有如下代码:
1 package com.sun.tools.javac;
2
3 /**
4 * @author TY
5 */
6 public class Foo {
7
8 public static void foo() {
9 int a = 0;
10 int b = 6;
11 int c = 130;
12 int d = 33000;
13 }
14
15 }
很简单的一段代码,看似没有什么值得讨论的地方,然而将代码用javap查看下字节码:

可以看到针对定义的不同的变量,字节码的指令是不同的,虽然都是整数。。。那为什么呢?简单分析就可以得知,是和
声明的值的大小有关系,针对不同的大小范围采用不同的字节码指令。但是如何验证我们的想法呢?相信很多人是不知道的。下面会讲到如何验证
我们的想法。
问题二:
再有如下代码:
1 package com.sun.tools.javac;
2
3 /**
4 * @author TY
5 */
6 public class Switch {
7
8 public static void foo() {
9 int a = 0;
10 switch (a) {
11 case 0:
12 System.out.println("#0");
13 break;
14 case 1:
15 System.out.println("#1");
16 break;
17 default:
18 System.out.println("default");
19 break;
20 }
21 }
22
23 }
简单的一段swtich...case逻辑,看着也没有什么问题,再看看字节码:

看到上面的字节码,采用的是looupswitch,而我们知道,switch...case语句底层有两种指令:tableswitch和looupswitch,之前我
在学习的时候就只是知道tableswtich适用于case值比较紧凑的情况,而lookupswitch适用于case值比较稀疏的情况。但是上面的代码
case值分别是0和1,,,这这这,算哪门子稀疏了,所以为什么要用lookupswitch而不用tableswtich呢?
Javac源码
我们知道将Java代码编译成字节码的命令是Javac,所以关于上面的问题,都应该在Javac的源码里面去找答案。
首先下载Javac的源码,这里我提供张师傅提供的地址:javac-source-code-reading
下载好之后用IDEA打开:

上面的out目录是我自己建的,不然运行javac的入口main函数会报错让指定class码输出目录。
新建了目录之后需要到项目设置里面设置:

然后将com.sun.tools下面的两个包给排除掉,不然编译通不过

这些做好之后就可以执行下javac的入口函数: com.sun.tools.javac.Main
直接执行来看看:

执行结果:

好熟悉的输出,这不是在命令行里面直接执行javac的输出吗?

所以,知道该怎么做了吧,需要加一个参数,参数就是要编译的java类的名字,我新建一个Hello类,随便写点啥。。。

然后将Hello类的路径填写到Main的传入参数里面:

再执行Main函数就可以看到Hello类的同级目录下就多了一个class文件:

这就说明我们可以跟着Javac的源代码进行调试了,不过在此之前需要设置下:

将Module source移到系统安装的JDK的前面,这样才能正常的调试而不是调试的时候跳转到安装的JDK里面去。
可以调试Javac的代码意味着很多东西,我们遇到不理解的字节码的时候可以跟着Javac源码走一遍,看人家到底是怎么去实现的。
接下来回到上面的两个问题,对应的Javac的源码分别在com.sun.tools.javac.jvm.Item类和com.sun.tools.javac.jvm.Gen类中,比如问题一代码对应下面:

可以看到针对值得大小不同走了不同的逻辑:
-1到5:iconst_0
-128到127:bipush
-32768到32767:sipush
然后超过以上的范围则是:ldc
而问题二对应的代码在Gen类visitSwitch方法中,重点代码是下面这段:

hi和lo是在的代码逻辑中分别指向case的最大和最小值。我们将case值0和1代入其中:
最终table_space_cost + 3 * table_time_cost = 15,而looup_space_cost + 3 * looup_time_cost = 13,
所以最终选用了lookupswitch指令。关于为什么要采用这样的算法我暂时不知,但至少对照着Javac源码知道了算法逻辑,不至于遇到
问题的时候一脸懵。。
总结
本文主要讲述了如何调试Javac源码以及如何运用Javac源码解答一些字节码的问题。
可以扫描下面我分享的二维码购买,会便宜几块钱。。。(土豪不用管)

跟随Javac代码来解答字节码的疑惑的更多相关文章
- 【计算机基础】IL代码-CLR平台上的字节码【什么是字节码?它与虚拟机的关系?】
字节码(英语:Bytecode)将虚拟机可以读懂的代码称之为字节码.将源码编译成虚拟机读的懂的代码,需要虚拟机转译后才能成为机器代码的中间代码 叫做字节码. 字节码主要为了实现特定软件运行和软件环境. ...
- 深入理解Java虚拟机(类文件结构+类加载机制+字节码执行引擎)
目录 1.类文件结构 1.1 Class类文件结构 1.2 魔数与Class文件的版本 1.3 常量池 1.4 访问标志 1.5 类索引.父索引与接口索引集合 1.6 字段表集合 1.7 方法集合 1 ...
- JVM字节码指令
invokevirtual 调用实例方法 invokespecial 调用父类构造,实例初始化方法,私有方法 dup 复制栈顶数值,并且复制值进栈,pop/pop2为栈顶值出栈 aload_0 加载第 ...
- JVM 字节码(二)方法表详解
JVM 字节码(二)方法表和属性表 上一节中对 ClassFile 的整体进行了五个详细的说明, 本节围绕 ClassFile 最重要的一个内容 - 方法表的 Code 属性展开 ,更多 JVM Me ...
- java虚拟机字节码执行引擎
定义 java虚拟机字节码执行引擎是jvm最核心的组成部分之一,它做的事情很简单:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果.在不同的虚拟机实现里,执行引擎在执行java代码 ...
- Berry 异常处理 1: 语法和字节码设计
语法 最近在实现 Berry 的异常处理特性,进过初步的调查后决定使用类似 Python 的 try-except 异常处理模式,为此要引入三个新的关键字: try:表示异常捕获块的开始,位于异常捕获 ...
- java动态代理——jvm指令集基本概念和方法字节码结构的进一步探究及proxy源码分析四
前文地址 https://www.cnblogs.com/tera/p/13336627.html 本系列文章主要是博主在学习spring aop的过程中了解到其使用了java动态代理,本着究根问底的 ...
- Java并发杂谈(一):volatile的底层原理,从字节码到CPU
volatile的特性 volatile是Java中用于修饰变量的关键字,其主要是保证了该变量的可见性以及顺序性,但是没有保证原子性:其是Java中最为轻量级的同步关键字: 接下来我将会一步步来分析v ...
- 【JVM】模板解释器--字节码的resolve过程
1.背景 上文探讨了:[JVM]模板解释器--如何根据字节码生成汇编码? 本篇,我们来关注下字节码的resolve过程. 2.问题及准备工作 上文虽然探讨了字节码到汇编码的过程,但是: mov %ra ...
随机推荐
- Spine学习二 -播放Spine动画
要想播放一个Spine动画,必须要在一个物体上绑定一个Spine播放的组件,这里暂时使用SkeletonAnimation组件. 然后就是编写动画的控制脚本. 这里提一个特性: [SpineAnima ...
- java初探(1)之登录总结
登录总结 前几章总结了登录各个步骤中遇到的问题,现在完成的做一个登录的案例,其难点不在于实现功能,而在于抽象各种功能模块,提高复用性,较低耦合度. 前端页面: 对于前端页面来说,不是后端程序员要考虑的 ...
- Prometheus 与 国产 TDengine 的对比
通过对比,能加深对这两个系统的理解,方便后续架构选型时作出正确决定.他们的设计思路有很多值得借鉴的地方,虽然工作中需要用到这些知识的地方不多,但是了解他们的设计细节能极大满足我的好奇心. 1.场景和需 ...
- 答应我,用了这个jupyter插件,别再重复造轮子了
1 简介 在使用Python.R等完成日常任务的过程中,可能会经常书写同样或模式相近的同一段代码,譬如每次使用matplotlib绘制图像的时候可以在开头添加下面两行代码来解决中文乱码等显示问题: p ...
- 05 element.ui 全局配置
element.ui css样式在组件里面改有的不会生效,是因为加了scoped.局部作用,放在这里是全局配置
- 14_Python语法示例(面向对象)
1.自己写一个Student类,此类的对象有属性name, age, score, 用来保存学生的姓名,年龄,成绩 # 1)写一个函数input_student读入n个学生的信息,用对象来存储这些信息 ...
- 6.AVCodecContext和AVCodec
AVCodecContext AVCodecContext 结构表示程序运行的当前 Codec 使用的上下文,着重于所有 Codec 共有的属性(并且是在程序运行时才能确定其值)和关联其他结构的字段 ...
- 基于jQuery的鼠标悬停时放大图片的效果制作
这是一个基于jQuery的效果,当鼠标在小图片上悬停时,会弹出一个大图,该大图会跟随鼠标的移动而移动.这个效果最初源于小敏同志的一个想法,刚开始做的时候只能实现弹出的图片是固定的,不能随鼠标移动,最后 ...
- 如何把Github上好的项目pull到本地或者fork到本地(码云仓库同理)?
首先Github账户的注册我就不想再啰嗦了,我想大家都会的. 其次怎么把自己的项目push到自己的Github仓库请参考我的另一篇博客: 如何把自己开发的项目上传到GitHub仓库或者码云仓库? 最后 ...
- 你想了解的分布式文件系统HDFS,看这一篇就够了
1.分布式文件系统 计算机集群结构 分布式文件系统把文件分布存储到多个节点(计算机)上,成千上万的计算机节点构成计算机集群. 分布式文件系统使用的计算机集群,其配置都是由普通硬件构成的,与用多个处理器 ...