当前位置: 首页 > news >正文

创建网站的免费软件国内萍乡网站建设公司

创建网站的免费软件国内,萍乡网站建设公司,优化wordpress访问,营销方案网站文章目录 前言1. if语句字节码的解析 2. for循环字节码的解析 3. while循环4. switch语句5. try-catch语句6. i 和i的字节码7. try-catch-finally8. 参考文档 前言 上一章我们聊了《JVM字节码指令详解》 。本章我们学以致用#xff0c;聊一下我们常见的一些java语句的特性底层… 文章目录 前言1. if语句字节码的解析 2. for循环字节码的解析 3. while循环4. switch语句5. try-catch语句6. i 和i的字节码7. try-catch-finally8. 参考文档 前言 上一章我们聊了《JVM字节码指令详解》 。本章我们学以致用聊一下我们常见的一些java语句的特性底层是如何实现。 1. if语句 if语句是我们最常用的判断语句之一它的底层实现原理是什么呢可以通过反编译字节码来分析一下。 假设我们有以下的java代码 public class IfStatement {public static void main(String[] args) {int a 10;if (a 0) {System.out.println(a is positive);} else {System.out.println(a is negative or zero);}} }可以使用javap命令来反编译字节码 javap -c IfStatement.class输出结果如下 public class IfStatement {// 构造方法public IfStatement();Code:0: aload_0 // 将局部变量表中的第0个元素通常是this引用入栈1: invokespecial #1 // 调用父类Object的构造方法4: return // 方法返回// main方法public static void main(java.lang.String[]);Code:0: bipush 10 // 将10压入栈顶2: istore_1 // 将栈顶元素10存入局部变量表的第1个位置3: iload_1 // 将局部变量表的第1个位置的元素10入栈4: ifle 17 // 判断栈顶元素10是否小于等于0如果是则跳转到指令177: getstatic #2 // 获取System类的out字段类型是PrintStream10: ldc #3 // 将字符串a is positive压入栈顶12: invokevirtual #4 // 调用PrintStream的println方法输出字符串15: goto 23 // 无条件跳转到指令2318: getstatic #2 // 获取System类的out字段类型是PrintStream21: invokevirtual #5 // 调用PrintStream的println方法输出局部变量表第1个位置的元素1024: return // 方法返回 }字节码的解析 在main方法中首先将10压入栈顶然后将其存入局部变量表的第1个位置。然后将局部变量表的第1个位置的元素10入栈判断其是否小于等于0如果是则跳转到指令17否则执行下一条指令。在指令7-15中它获取System的out字段将字符串a is positive压入栈顶然后调用println方法输出这个字符串最后无条件跳转到指令23。在指令18-21中它获取System的out字段然后调用println方法输出局部变量表第1个位置的元素10。最后main方法返回。 2. for循环 for循环是我们常用的循环语句之一它的底层实现原理是什么呢我们还是可以通过反编译字节码来分析一下。 假设我们有以下的java代码 public class ForLoop {public static void main(String[] args) {for (int i 0; i 10; i) {System.out.println(i i);}} }可以使用javap命令来反编译字节码 javap -c ForLoop.class这是一个包含for循环的Java类ForLoop的字节码输出下面是中文注释 public class ForLoop {// 构造方法public ForLoop();Code:0: aload_0 // 将局部变量表中的第0个元素通常是this引用入栈1: invokespecial #1 // 调用父类Object的构造方法4: return // 方法返回// main方法public static void main(java.lang.String[]);Code:0: iconst_0 // 将0压入栈顶1: istore_1 // 将栈顶元素0存入局部变量表的第1个位置2: iload_1 // 将局部变量表的第1个位置的元素0入栈3: bipush 10 // 将10压入栈顶5: if_icmpge 19 // 如果局部变量表的第1个位置的元素0大于等于栈顶元素10则跳转到指令198: getstatic #2 // 获取System类的out字段类型是PrintStream11: new #3 // 创建一个StringBuilder类的对象14: dup // 复制栈顶元素此时栈顶有两个相同的StringBuilder对象引用15: invokespecial #4 // 调用StringBuilder类的构造函数初始化对象18: ldc #5 // 将字符串i 压入栈顶20: invokevirtual #6 // 调用StringBuilder的append方法将字符串添加到StringBuilder23: iload_1 // 将局部变量表的第1个位置的元素0入栈24: invokevirtual #7 // 调用StringBuilder的append方法将数字添加到StringBuilder27: invokevirtual #8 // 调用StringBuilder的toString方法将StringBuilder转化为字符串30: invokevirtual #9 // 调用PrintStream的println方法输出字符串33: iinc 1, 1 // 将局部变量表的第1个位置的元素0增加136: goto 2 // 无条件跳转到指令2形成循环39: return // 方法返回LineNumberTable:line 3: 0line 4: 8line 3: 33line 6: 39StackMapTable: number_of_entries 2frame_type 252 /* append */offset_delta 2locals [ int, int ]stack []frame_type 250 /* chop */offset_delta 36 }字节码的解析 可以看到for循环的底层实现是通过if_icmpge指令来实现的。在本例中当i小于10时会执行第8行的输出语句否则会跳转到第39行结束循环。 在main方法中首先将0压入栈顶然后将其存入局部变量表的第1个位置。接下来是一个循环循环条件是局部变量表的第1个位置的元素小于10。在循环体中它首先获取System的out字段然后创建一个StringBuilder对象并初始化然后将字符串i 和局部变量表的第1个位置的元素添加到StringBuilder然后将StringBuilder转化为字符串然后调用println方法输出字符串。在循环体结束时它将局部变量表的第1个位置的元素加1然后无条件跳转到指令2形成循环。当循环结束时main方法返回。 3. while循环 while循环是我们常用的循环语句之一它的底层实现原理是什么呢我们还是可以通过反编译字节码来分析一下。 假设我们有以下的java代码 public class WhileLoop {public static void main(String[] args) {int i 0;while (i 10) {System.out.println(i i);i;}} }可以使用javap命令来反编译字节码 javap -c WhileLoop.class输出结果如下 public class WhileLoop {public WhileLoop();Code:0: aload_01: invokespecial #1 // Method java/lang/Object.init:()V4: returnpublic static void main(java.lang.String[]);Code:0: iconst_01: istore_12: iload_13: bipush 105: if_icmpge 198: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;11: new #3 // class java/lang/StringBuilder14: dup15: invokespecial #4 // Method java/lang/StringBuilder.init:()V18: ldc #5 // String i 20: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;23: iload_124: invokevirtual #7 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;27: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;30: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V33: iinc 1, 136: goto 239: returnLineNumberTable:line 3: 0line 4: 2line 5: 8line 6: 33line 5: 36line 8: 39StackMapTable: number_of_entries 2frame_type 252 /* append */offset_delta 2locals [ int, int ]stack []frame_type 250 /* chop */offset_delta 36 }可以看到while循环的底层实现也是通过if_icmpge指令来实现的。在本例中当i小于10时会执行第8行的输出语句否则会跳转到第39行结束循环。 4. switch语句 switch语句是我们常用的分支语句之一它的底层实现原理是什么呢我们还是可以通过反编译字节码来分析一下。 假设我们有以下的java代码 public class SwitchStatement {public static void main(String[] args) {int i 2;switch (i) {case 1:System.out.println(i is 1);break;case 2:System.out.println(i is 2);break;case 3:System.out.println(i is 3);break;default:System.out.println(i is neither 1, 2 nor 3);break;}} }可以使用javap命令来反编译字节码 javap -c SwitchStatement.class输出结果如下 public class SwitchStatement {public SwitchStatement();Code:0: aload_01: invokespecial #1 // Method java/lang/Object.init:()V4: returnpublic static void main(java.lang.String[]);Code:0: iconst_21: istore_12: iload_13: tableswitch { // 1 to 31: 282: 403: 52default: 64}28: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;31: ldc #3 // String i is 133: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V36: goto 7140: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;43: ldc #5 // String i is 245: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V48: goto 7152: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;55: ldc #6 // String i is 357: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V60: goto 7164: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;67: invokevirtual #7 // Method java/io/PrintStream.println:()V70: return71: returnLineNumberTable:line 3: 0line 4: 2line 5: 28line 6: 40line 7: 52line 8: 64line 9: 70line 7: 71StackMapTable: number_of_entries 5frame_type 252 /* append */offset_delta 28locals [ int ]frame_type 252 /* append */offset_delta 11locals [ int ]frame_type 252 /* append */offset_delta 12locals [ int ]frame_type 252 /* append */offset_delta 12locals [ int ]frame_type 252 /* append */offset_delta 3locals [ int ]可以看到switch语句的底层实现是通过tableswitch指令来实现的。在本例中当i等于1时会执行第28行的输出语句当i等于2时会执行第40行的输出语句当i等于3时会执行第52行的输出语句否则会执行第64行的输出语句。 5. try-catch语句 try-catch语句是我们常用的异常处理语句之一它的底层实现原理是什么呢我们还是可以通过反编译字节码来分析一下。 假设我们有以下的java代码 public class TryCatchStatement {public static void main(String[] args) {try {int[] arr new int[3];arr[4] 5;} catch (ArrayIndexOutOfBoundsException e) {System.out.println(Array index out of bounds!);}} }可以使用javap命令来反编译字节码 javap -c TryCatchStatement.class输出结果如下 public class TryCatchStatement {public TryCatchStatement();Code:0: aload_01: invokespecial #1 // Method java/lang/Object.init:()V4: returnpublic static void main(java.lang.String[]);Code:0: iconst_01: newarray int3: astore_14: aload_15: iconst_46: iconst_57: iastore8: goto 1911: astore_112: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;15: ldc #3 // String Array index out of bounds!17: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V20: returnException table:from to target type0 8 11 Class java/lang/ArrayIndexOutOfBoundsExceptionLineNumberTable:line 3: 0line 4: 4line 5: 11line 6: 12line 7: 20StackMapTable: number_of_entries 2frame_type 34 /* same */frame_type 1 /* same_locals_1_stack_item */stack [ class java/lang/ArrayIndexOutOfBoundsException ] }可以看到try-catch语句的底层实现是通过异常表来实现的。在本例中当数组下标越界时会执行第12行的输出语句否则会跳转到第20行继续执行。 6. i 和i的字节码 i 和 i 在语义上有些许不同在字节码层面也有所体现。下面是它们的字节码层面的解释 假设 i 是局部变量表的索引为1的变量。 i 的伪字节码 iload_1 // 从局部变量表中加载变量 i 到操作数栈顶 iinc 1 by 1 // 将局部变量表中的变量 i 增加1i 的伪字节码 iinc 1 by 1 // 将局部变量表中的变量 i 增加1 iload_1 // 从局部变量表中加载变量 i 到操作数栈顶可以看到i 与 i 的主要区别在于加载和增加操作的顺序不同。i 是先将 i 加载到操作数栈顶然后再增加 i 的值而 i 是先增加 i 的值然后再将 i 加载到操作数栈顶。这就解释了 i 和 i 在语义上的不同i 是先取值后加1i 是先加1后取值。 7. try-catch-finally 在 Java 字节码中try-catch-finally 结构主要通过异常表Exception Table来实现。Java 字节码并没有专门的指令来表示 try、catch 或者 finally 块。相反它通过在异常表中记录 try 块的开始和结束位置、catch 块的开始位置和要捕获的异常类型以实现异常处理的流程。 下面是一个简单的 try-catch-finally 代码例子 void test() {try {System.out.println(try block);throw new Exception();} catch (Exception e) {System.out.println(catch block);} finally {System.out.println(finally block);} }对应的字节码指令 0: getstatic #2 // 获取 java/lang/System 类的 out 字段是 PrintStream 类型 3: ldc #3 // 将常量池中的 try block 字符串压入栈顶 5: invokevirtual #4 // 调用 PrintStream 类的 println 方法输出字符串 8: new #5 // 创建一个 java/lang/Exception 类的对象 11: dup // 复制栈顶的元素此时栈顶有两个相同的异常对象引用 12: invokespecial #6 // 调用 Exception 类的构造函数初始化对象 15: athrow // 抛出栈顶的异常对象 16: astore_1 // 捕获异常并存入局部变量表的第1个位置 17: getstatic #2 // 获取 java/lang/System 类的 out 字段是 PrintStream 类型 20: ldc #7 // 将常量池中的 catch block 字符串压入栈顶 22: invokevirtual #4 // 调用 PrintStream 类的 println 方法输出字符串 25: jsr 26 // 无条件跳转到指令26finally块的起始位置 28: goto 34 // 执行完finally块后跳过 catch 块剩下的代码进入下一个处理流程 31: astore_2 // 捕获从finally块抛出的异常并存入局部变量表的第2个位置 32: jsr 26 // 无条件跳转到指令26finally块的起始位置 35: aload_2 // 从局部变量表的第2个位置加载异常对象至栈顶 36: athrow // 再次抛出该异常对象 37: astore_3 // 捕获异常并存入局部变量表的第3个位置 38: getstatic #2 // 获取 java/lang/System 类的 out 字段是 PrintStream 类型 41: ldc #8 // 将常量池中的 finally block 字符串压入栈顶 43: invokevirtual #4 // 调用 PrintStream 类的 println 方法输出字符串 46: ret 3 // 返回到 astore_3 指令之后的代码这段字节码中使用了 jsr 和 ret 指令这两个指令主要用于实现 finally 块的逻辑。jsr 指令会跳转到 finally 块的代码然后 ret 指令用于返回到 finally 块之前的代码继续执行。 字节码的解释 行0-15这部分对应 try 块的内容。在这个例子中它首先通过 getstatic 指令获取 System.out 对象然后通过 ldc 指令加载常量 “try block”最后调用 println 方法输出这个字符串。然后它创建一个 Exception 对象并抛出。 行16-25这部分对应 catch 块的内容。当 try 块抛出异常时执行流程会跳转到这部分。在这个例子中它首先通过 astore 指令将异常对象存储到局部变量表然后类似于 try 块的处理输出 “catch block” 字符串。 行37-46这部分对应 finally 块的内容。无论 try 块是否抛出异常这部分代码总是会被执行。在这个例子中它输出 “finally block” 字符串。 行25-32和行35-36这部分是对异常处理的一些额外控制。jsr 和 ret 指令用于实现无条件的跳转确保 finally 块总是会被执行。 8. 参考文档 张亚 《深入理解JVM字节码》https://www.jonesjalapat.com/2021/09/11/internal-working-of-java-virtual-machine/
http://www.w-s-a.com/news/607949/

相关文章:

  • 网站制作软件排行榜上海市网站建设公司58
  • 什么是网站风格中国工商网企业查询官网
  • 专业建设专题网站wordpress lnmp wamp
  • 环保网站 下载页网站
  • 开源小程序模板江门关键词优化排名
  • 网站开发 知乎房地产型网站建设
  • 买完域名网站怎么设计wordpress 纯代码
  • 公司网站怎么做百度竞价宁波网络公司哪家好
  • 河西网站建设制作微信分销系统多层
  • 网站制作完成后应进入什么阶段石家庄网站建设找哪家好
  • 南通外贸网站推广自在源码网官网
  • 个人网站模板html下载餐饮vi设计案例欣赏
  • 高端网站建设wanghess网站开发售后服务承诺
  • 江西网站建设费用企业网站推广的方法有( )
  • 中国十大网站开发公司企业网站建设的要素有哪些
  • 网站防站做网站吉林
  • 嘉定区网站建设公司企业信息公示查询系统官网
  • 一个具体网站的seo优化产品介绍网站模板下载地址
  • 怎么做网站在网上能搜到你哈尔滨网站建立公司
  • 做家旅游的视频网站上海百度公司总部
  • 微信小程序公司网站怎么制作区块链平台定制开发
  • 网站资质优化ip地址域名解析
  • 如何搭建个人网站ps做网站首页怎么运用起来
  • 中小企业商务网站建设wordpress 安全加固
  • asp网站开发设计文档php建设网站怎么用
  • 服装公司网站建设需求分析报告seo搜索引擎优化实战
  • wordpress 扒站最近最新新闻
  • 手机wap网站开发与设计wordpress域名无法访问
  • 百度收录网站收费吗做网站用vs还是dw
  • 维度网络专业做网站嘉兴网站建设方案服务