首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

javac 源码调试教程来了

为什么写这这篇文章 一直读者问我 javac 源码怎么调试,自己也在写 JVM 掘金小册过程中阅读了大量 javac 源码,网上这方面的文章比较少,那就来写一篇 javac 源码调试文章吧,作为...javac 看字节码案例一:tableswitchlookupswitch 选择策略 读者提问,下面的代码编译出 switch-case 语句为什么采用了 lookupswitch,而不是 tableswitch...,不是说「如果 case 值比较紧凑,中间少量断层或者没有断层,会采用 tableswitch 来实现 switch-case」吗?...这里算法导致选择了 lookupswitch javac 看字节码案例二:加载整数到栈上字节指令选择 我们知道很多指令可以把整数加载到栈上,比如iconst_0、bipush、sipush、ldc...sipush 其它大整数选择 ldc 这与 java 虚拟机规范中字节指令文档一致。

45510

why哥被一道基础面试题给干懵了,一气之下写出万字长文。

奇怪了,同样 switch 语言,却对应两个指令lookupswitchtableswitch。 所以这两个指令肯定是关键突破点。 我们去哪里找这个两个指令信息呢?...左边是 java 文件,里面的 case 只有 0、2、4。 右边是字节码文件, tableswitch 里面有0、1、2、3、4。 对应 class 文件是这样: ? 嘿,你说怎么着?...你看左边 java 代码,里面的 case 是乱序字节码文件里面后就排好序了。 而官方文档里面说这个“table”: ? 就是排好序这个: ? 为什么要排序呢?...tableswitch 由于是直接根据偏移量定位,所以时间复杂度是 O(1)。 好了,这里我就把 tableswitchlookupswitch 这两个指令讲完了。...这里个三目表达式。如果为真则使用 tableswitch ,为假则使用 lookupswitch。 我们先拿着这个不稀疏,加上断点调戏一番,呸,调试一番: ? 断点时候时候各个参数如下: ?

60410
您找到你想要的搜索结果了吗?
是的
没有找到

解密switch背后秘密

以及为什么原因将在本文为你揭晓。...switch 秘密 对于 switch 来说,他最终生成字节两种形态,一种是 tableswitch,另一种是 lookupswitch,决定最终生成代码使用那种形态取决于 switch 判断添加是否紧凑...,例如 case 是 1...2...3...4 这种依次递增判断条件时,使用tableswitch,而像 case 是 1...33...55...22 这种非紧凑型判断条件时则会使用 lookupswitch...而 switch 在编译为字节码时,会根据 switch 判断条件是否紧凑生成两种代码:tableswitch(紧凑时生成)和 lookupswitch(非紧凑时生成),其中 tableswitch...是采用类似于数组存储结构,直接根据索引查询元素;而 lookupswitch 则需要逐个查询或者使用二分法查询,因此 tableswitch 性能会比 lookupswitch 性能高,但无论如何

2K40

大多数程序员都懂java虚拟机:C1编译器从字节HIR

字节HIR 正如之前看到,C1HIR是一个基于静态单赋值图IR,由基本块构成控制流图,由静态单赋值指令构成基本块,如图8-1所示。...识别基本块 字节码是线性结构,所以在识别时可以使用BlockListBuilder线性地遍历字节码,找到if_cmp*、goto、throw、return、tableswitchlookupswitch...左侧[i7,i8]表示局部变量,当解释iload_1时,加载局部变量i8ValueStack中,该字节码不生成SSA指令;当解释iload_0时,加载i7ValueStack,该字节码不生成SSA...指令;当解释imul时,该字节码会生成SSA指令,该指令以ValueStack两个值作为参数,产出新值i11并放入ValueStack;当解释istore_1时,将i11放入局部变量表第二个槽,该字节码不产生...解释完成后生成三条SSA指令填充到基本块中,至此HIR构造就完成了,之前基于栈字节码变成了基于寄存器SSA指令

58120

Java代码原来是这么执行—怒撕字节指令

与汇编语言相似之处就是字节指令不能直接将局部变量表某个元素赋值给局部变量表另一个元素,必须通过操作数栈完成。这也是为什么字节指令集是基于栈指令集。...以上面例子说明,tableswitch指令对应字节码为: ? 第一个字节0xAA是tableswitch指令操作码,后面每四个字节为一个操作数。...显然,这种情况下再使用tableswitch指令是不可取。 正如你所看到,编译器使用lookupswitch指令替代了tableswitch指令。...lookupswitch指令操作码为0xAB,与tableswitch指令一样,该指令操作数也是不定长,每个操作数长度为四个字节,操作数存放也是下一条字节指令相对偏移量,注意,还是相对偏移量...第一个字节0xAB是lookupswitch指令操作码,接着后面四个字节也是匹配default时跳转目标指令相对当前指令偏移量,紧随其后四个字节0x00000002代表后面跟随多少个条件映射,每八个字节为一个条件映射

96610

浮点数0不是0,怀疑人生了

记录最近遇到一些坑点,分享给常在河边走你。 1、老师告诉我分母不能是0。 场景:项目个功能是竞猜功能,竞猜需要金币是根据公式: M+ N*0.5/ diffDays。...M是根据玩家等级策划配置值,N是某一天当前时间收入总和,diffDays 是收入天数。 在测试时候,测试同学发现在玩家有14亿金币仍然不能竞猜,这很奇怪。...经过调试发现diffDays 为0,为什么0不报错呐?老师告诉我不对吗? 难受。...想要知道为什么一切还要从源头说起:字节码 可以看到switch case 被编译成Lookupswitch ,两个case 被编译为L2,L3 ,并且自动添加了default L4。...除了Lookupswitch 还有 tableswitch ,具体区别 你知道吗?下期再说哦。

35940

如何找个对象(指令)

假期已经接近尾声了,新一年废话不多说,直接开干,话说大家今年有没有领”对象“回家,祝对象情人节快乐,没有对象没关系看完这篇文章就知道如何找个”对象“了,相约下一年和下一个情人节,今天主要讲几个指令类型...、lookupswitch 无条件分支:goto、goto_w、jsr、jsr_w、ret 对于boolean、byte、char和short类型条件分支比较操作,都采用int类型比较指令来完成,而对于...long、float、double类型条件分支比较操作,则会先执行相应类型比较运算指令(dcmpg、dcmpl、fcmpg、fcmpl、lcmp),比较运算指令会返回一个整型值操作数栈中,然后再执行...由于我们这边a值为1,因此会将-1压入操作数栈中 3:下面采用ifle条件分支比较指令,从下图中我们可以得知ifle会将栈顶元素与0比较,只有栈顶元素小于等于0是结果才为true,由于栈顶元素是-1...本期JVM指令就介绍这,我们下期再见!!!

24520

为什么switch里case没有break不行

小姐姐接着问我为什么,我说少个break,但凡再问一句:为什么少个break结果就不一样,我就回答不出来了。所以,为了将尴尬扼杀于摇篮,还是研究一下break在switch作用。...javac编译和javap查看: 「tableswitch」和「lookupswitch」都用于switch条件跳转,前者用于case值连续,例如上面代码中0、1、2;后者用于case值不连续。...如图,与第一次字节码相比,在标号35、45都有了goto指令。...如果case 0匹配成功,则跳到标号28执行,执行完代码块对应31、32指令之后,执行35goto指令跳转到标号55,这样就跳出了switch作用范围,case 1和2也不会被执行。...从字节码也可以看出if和switch区别:if条件和代码块字节码是顺序,switch条件和代码块是分开;if自动生成goto指令,switch只有加了break才生成goto指令

67220

java虚拟机JVM编译器编译代码简介 字节指令实例 代码到底编译成了什么形式

前言简介 前文已经对虚拟机进行过了简单介绍,并且也对class文件结构,以及字节指令进行了详尽说明 想要了解JVM运行机制,以及如何优化你代码,你还需要了解一下,java编译器到底是如何编译你代码...本文不是从最底层编译原理讲解 本文是针对java代码,去查看归纳总结编译器结果行为,从而直观感受到字节指令集 也就是说本文内容,主要针对是使用javap 查看字节码文件中方法code...属性中字节码内容 让你从java代码  class文件格式,以及字节指令集 进行一个直观演示 提醒: 如果你对字节指令不了解,而且,没有看过前面的文章,本文可能会轻度不适....本文示例只是为了展示 您应该经常查看你自己代码class文件去发现其中规律 一条普通指令格式 [ [ ... ]]...hashCode12, lookupswitch表中,不在类似tableswitch 了,那个是连续lookupswitch  是不连续我们总共有三个case一个default lookupswitch

55920

JVM学习第三天(JVM执行子系统)之字节指令

早上看了Class类文件结构,晚上继续来看字节指令,毕竟谁也不是一步登天(说白了还是穷); ?...字节指令 Java虚拟机指令由一个字节长度、代表着某种特定操作含义数字(称为操作码,Opcode)以及跟随其后零至多个代表此操作所需参数(称为操作数,Operands)而构成。...由于限制了Java虚拟机操作码长度为一个字节(即0~255),这意味着指令操作码总数不可能超过256条。 大多数指令都包含了其操作所对应数据类型信息。...复合条件分支:tableswitchlookupswitch。 无条件分支:goto、goto_w、jsr、jsr_w、ret。...今天懂得了一个道理,那就是人生不止技术;决定在自己板块中添加一个人生不止技术分类,相信同样情况的人,也不止我一个; 本来打算今天晚上早点睡,然后明天早上学习,但是还是忍不住又看了一个小时,

51130

JVM进阶之路】十二:字节指令

在前面的 【JVM进阶之路】三:探究虚拟机对象 里,提到了对象初始化过程,对象初始化用是new指令——这就是字节指令。...在【JVM进阶之路】十一:Class文件结构 中已经学习了JVM 字节码是JVM能直接识别的语言,了解了字节码文件文件结构。接下来,我们进一步学习字节相关指令。...2)窄化,大类型向小类型转换,比如从 int 类型 byte、short 或者 char,对应指令:i2b、i2s、i2c;从 long int,对应指令:l2i;从 float int...或者 long,对应指令:f2i、f2l;从 double int、long 或者 float,对应指令:d2i、d2l、d2f。...、if_icmple、if_icmpge、if_acmpeq和if_acmpne 复合条件分支:tableswitchlookupswitch 无条件分支:goto、goto_w、jsr、

82330

jvm之类文件详解(四)

字节码介绍 字节码与数据类型 • 在虚拟机指令集中,大多数指令包含了其操作所对应数据类型信息 • iLoad:从局部变量表中加载int型数据操作数栈 • 大多数指令包含类型信息 • 类型多...2 b I // 10 8 3 c I } 运算指令 • 运算或算术指令用于对两个操作数栈上值进行某种特定运算,并把结果存储操作数栈顶...类型转换指令 • 类型转换指令可以将两种不同数值类型进行相互转换,这些转换操作一般用于实现用户代码中显示类型转换操作以 及用来处理字节指令集中数据类型相关指令无法与数据类型一一对应问题 •...• 把数组元素加载到操作数栈指令:aload • 将操作数栈值存储数组元素:astore • 取数组长度指令:arraylength • 检查实例类型指令:instanceof checkcast...可以认为控制转移指令就是在修改pc寄存器值 • 条件分支:ifeq iflt ifle ifne ifgt ifnull ifcmple • 复合条件分支:tableswitch lookupswitch

17550

Java 字节指令,让我发了疯疯疯!

但涌进来的人越多,就意味着越来越卷,要想不被卷,就必须得疯狂学习,学什么呢?Java 字节指令就是一块硬骨头。 有些读者可能会有这样疑惑,“Java 字节码难吗?Java 虚拟机难吗?...和 short int 宽化类型转换实际上是隐式发生,这样可以减少字节指令,毕竟字节指令只有 256 个,占一个字节。...2)窄化,大类型向小类型转换,比如从 int 类型 byte、short 或者 char,对应指令:i2b、i2s、i2c;从 long int,对应指令:l2i;从 float int...或者 long,对应指令:f2i、f2l;从 double int、long 或者 float,对应指令:d2i、d2l、d2f。...4)多条件分支跳转指令 主要有 tableswitchlookupswitch,前者要求多个条件分支值是连续,它内部只存放起始值和终止值,以及若干个跳转偏移量,通过给定操作数 index,可以立即定位跳转偏移量位置

43710

java 操作码

操作码介绍 我们都知在Java中我们类会被编译成字节码然后放到虚拟机中去执行,字节码里面的内容其实我们也是可以去“阅读”,方法就是通过 jdk自带工具翻译成操作码。...在操作码中我们能看到一些我们平时看不到关于java秘密。 Java虚拟机指令由一个字节长度数字以及跟随其后零至多个代表此操作所需参数构成。即:Java指令 = 操作码 + 操作数。...9 0 args [Ljava/lang/String; } 有的小伙伴可能没有将 jdkbin目录配置环境变量,执行javap指令时候识别不了该指令,我们只需要指定指令全路径就...数据类型相关 iload指令用于从局部变量表中加载int型数据操作数栈中; fload指令则是从局部变量表中加载float类型数据操作数栈中; i代表int类型,l代表long类型,s代表short...无条件分支 goto、goto_w、jsr、jsr_w、ret 复合条件分支tableswitchlookupswitch 方法调用相关 方法返回值类型表示方式 ()V 表示 void 方法 ()

39020

java黑科技-操作码

在操作码中我们能看到一些我们平时看不到关于java秘密。 Java虚拟机指令由一个字节长度数字以及跟随其后零至多个代表此操作所需参数构成。即:Java指令 = 操作码 + 操作数。...9 0 args [Ljava/lang/String; } 有的小伙伴可能没有将 jdkbin目录配置环境变量,执行javap指令时候识别不了该指令,我们只需要指定指令全路径就ok...数据类型相关 iload指令用于从局部变量表中加载int型数据操作数栈中; fload指令则是从局部变量表中加载float类型数据操作数栈中; i代表int类型,l代表long类型,s代表short..._等 将一个数值从操作数栈存储局部变量表,istore、istore_、lstore、lstore_、astore、astore_等 将一个常量加载到操作数栈,bipush...goto、goto_w、jsr、jsr_w、ret 复合条件分支tableswitchlookupswitch 方法调用相关 方法返回值类型表示方式 ()V 表示 void 方法 ()Ljava/lang

48220

JVM Specification notes 1 -Jvm Structure

摘要: Jvm Structure 正文: Java 虚拟机结构 Class文件格式 数据类型 原始类型(基本类型) 数值类型{整数[byte8 short16 int32 long64 char16...Java虚拟机提供一些字节指令来从局部变量表或者对象实例字段中复制常量或变量值操作数栈中,也提供了一些指令用于从操作数栈取走数据、操作数据和把操作结果重新入栈。...在方法调用时候,操作数栈也用来准备调用方法参数以及接收方法返回结果,例子参考初识jvm指令执行流程 一个long或者double类型数据会占用两个单位栈深度,其他数据类型则会占用一个单位深度...,如果能找到可以处理该异常异常处理器,则将代码控制权转向异常处理器中描述处理异常分支之中 字节指令 Java虚拟机指令由一个字节长度、代表着某种特定操作含义操作码(Opcode)以及跟随其后零至多个代表此操作所需参数操作数...指令集序列同步 通常是由Java语言synchronized块来表示,java虚拟机指令monitorenter和monitorexit两条指令来支持synchronized关键字语义

82770

JVM基础命令

介绍java虚拟机指令功能,至少能阅读java代码生成字节指令含义 一、概述 Java虚拟机采用基于栈架构,其指令由操作码和操作数组成。...操作码:一个字节长度(0~255),意味着指令操作码个数不能操作256条。 操作数:一条指令可以零或者多个操作数,且操作数可以是1个或者多个字节。...二、指令 大多数指令包含了其操作所对应数据类型信息,比如iload,表示从局部变量表中加载int型数据操作数栈;而fload表示加载float型数据操作数栈。...2.5 流程控制 控制指令是指有条件或无条件地修改PC寄存器值,从而达到控制流程目标 条件分支:ifeq、iflt、ifnull、ifnonnull等 复合分支:tableswitchlookupswitch...2.7 小结 在基于堆栈虚拟机中,指令主战场便是操作数栈,除了load是从局部变量表加载数据操作数栈以及store储存数据局部变量表,其余指令基本都是用于操作数栈

77570

JVM指令手册

栈和局部变量操作 将常量压入栈指令 aconst_null 将null对象引用压入栈 iconst_m1 将int类型常量-1压入栈 iconst_0 将int类型常量0压入栈 iconst_1 将int...wide 使用附加字节扩展局部变量索引 通用(无类型)栈操作 nop 不做任何操作 pop 弹出栈顶端一个字长内容 pop2 弹出栈顶端两个字长内容 dup 复制栈顶部一个字长内容 dup_x1...分配数据成员类型为引用类型新数组 arraylength 获取数组长度 multianewarray 分配新多维数组 控制流 条件分支指令 ifeq 如果等于0,则跳转 ifne 如果不等于0,则跳转...goto 无条件跳转 goto_w 无条件跳转(宽索引) 表跳转指令 tableswitch 通过索引访问跳转表,并跳转 lookupswitch 通过键值匹配访问跳转表,并执行跳转操作 异常 athrow...从方法中返回,返回值为void 线程同步 montiorenter 进入并获取对象监视器 monitorexit 释放并退出对象监视器 JVM指令助记符 变量到操作数栈:iload,iload_,lload

1.1K51

Javap -c 字节码解析

栈和局部变量操作 将常量压入栈指令 aconst_null         将null对象引用压入栈 iconst_m1         将int类型常量-1压入栈 iconst_0        ...wide             使用附加字节扩展局部变量索引 通用(无类型)栈操作nop             不做任何操作 pop             弹出栈顶端一个字长内容 pop2...goto             无条件跳转 goto_w             无条件跳转(宽索引) 表跳转指令 tableswitch         通过索引访问跳转表,并跳转 lookupswitch...释放并退出对象监视器 *********************************************************************** JVM指令助记符 变量到操作数栈:iload...,lookupswitch 无条件转移:goto,goto_w,jsr,jsr_w,ret 调度对象实便方法:invokevirtual 调用由接口实现方法:invokeinterface 调用需要特殊处理实例方法

68060
领券