首页 > 其他分享 >OpenJDK17.0.8字节码解读样例

OpenJDK17.0.8字节码解读样例

时间:2023-08-26 18:33:05浏览次数:38  
标签:java 字节 OpenJDK17.0 栈顶 样例 int 本地 Utf8 变量

  因为JDK17将会成为未来5至10年里Java应用的主流JDK,刚好闲着没事,就想着将《深入理解Java虚拟机》一书中关于字节码的解读样例在OpenJDK17.0.8上看看变化有多大!

  先把实验环境说明一下:

  OS:Windows 10 专业版 22H2

  JDK:openjdk version "17.0.8" 2023-07-18 LTS

  源码如下:

 1 package org.example.chapter1;
 2 
 3 public class TestClass {
 4     private int m;
 5 
 6     public int inc() {
 7         int x;
 8         try {
 9             x = 1;
10             return x;
11         } catch (Exception e) {
12             x = 2;
13             return x;
14         } finally {
15             x = 3;
16         }
17     }
18 }

  使用JDK自带的工具 javac 编译后,再用JDK自带的工具 javap 对编译出来的 *.class 文件解析出来的字节码如下(添加了说明):

#使用的 javap 命令和选项如下
javap -verbose -l org.example.chapter1.TestClass
Classfile /E:/Projects/demo001/src/main/java/org/example/chapter1/TestClass.class
  Last modified 2023年8月26日; size 457 bytes
  SHA-256 checksum 93dd8cecee43cd228708aed7079cc1b41502cb2279b365cdbf59e74e8c8c057f
  Compiled from "TestClass.java"
public class org.example.chapter1.TestClass
  minor version: 0                        //Class文件【次版本号】
  major version: 61                       //Class文件【主版本号】
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER   //访问标志组合
  this_class: #9                          // org/example/chapter1/TestClass
  super_class: #2                         // java/lang/Object
  interfaces: 0, fields: 1, methods: 2, attributes: 1
Constant pool:                            //常量池
   #1 = Methodref          #2.#3          // java/lang/Object."<init>":()V
   #2 = Class              #4             // java/lang/Object
   #3 = NameAndType        #5:#6          // "<init>":()V
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Class              #8             // java/lang/Exception
   #8 = Utf8               java/lang/Exception
   #9 = Class              #10            // org/example/chapter1/TestClass
  #10 = Utf8               org/example/chapter1/TestClass
  #11 = Utf8               m
  #12 = Utf8               I
  #13 = Utf8               Code
  #14 = Utf8               LineNumberTable
  #15 = Utf8               inc
  #16 = Utf8               ()I
  #17 = Utf8               StackMapTable
  #18 = Class              #19            // java/lang/Throwable
  #19 = Utf8               java/lang/Throwable
  #20 = Utf8               SourceFile
  #21 = Utf8               TestClass.java
{
  public org.example.chapter1.TestClass();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0

  public int inc();
    descriptor: ()I
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=5, args_size=1
         0: iconst_1            //将 int 型 1 推送至栈顶(进入try代码块)
         1: istore_1            //将栈顶 int 型数值存入第二个本地变量(对应try代码块里的 x=1;)
         2: iload_1             //将第二个 int 型本地变量推送至栈顶(x压入栈顶,此时x=1)
         3: istore_2            //将栈顶 int 型数值存入第三个本地变量(将栈顶的x存入该三号隐式本地变量中暂存)
         4: iconst_3            //将 int 型 3 推送至栈顶(进入finally代码块)
         5: istore_1            //将栈顶 int 型数值存入第二个本地变量(对应finally代码块里的 x=3;)
         6: iload_2             //将第三个 int 型本地变量推送至栈顶(三号隐式本地变量中暂存的x=1压入栈顶)
         7: ireturn             //将栈顶 int 型数值作为返回值返回(即返回了栈顶的x=1,方法未出现异常的情况执行结束!)
         8: astore_2            //将栈顶 引用 型数值存入第三个本地变量(栈顶当前存放的是某个显式异常实例对象的引用,到达catch代码块,复用了三号隐式本地变量,之后就没有对该变量做任何操作了,因为异常实例e没有在后续代码中使用)
         9: iconst_2            //将 int 型 2 推送至栈顶(进入catch代码块)
        10: istore_1            //将栈顶 int 型数值存入第二个本地变量(对应catch代码块里的 x=2;)
        11: iload_1             //将第二个 int 型本地变量推送至栈顶(x压入栈顶,此时x=2)
        12: istore_3            //将栈顶 int 型数值存入第四个本地变量(将栈顶的x存入该四号隐式本地变量中暂存)
        13: iconst_3            //将 int 型 3 推送至栈顶(进入finally代码块)
        14: istore_1            //将栈顶 int 型数值存入第二个本地变量(对应finally代码块里的 x=3;)
        15: iload_3             //将第四个 int 型本地变量推送至栈顶(四号隐式本地变量中暂存的x=2压入栈顶)
        16: ireturn             //将栈顶 int 型数值作为返回值返回(即返回了栈顶的x=2,方法出现显式异常的情况执行结束!)
        17: astore        4     //将栈顶 引用 型数值存入第五个本地变量(将栈顶的某个隐式异常实例对象的引用存入该五号隐式本地变量中暂存,出现显式代码无法捕获的其他异常)
        19: iconst_3            //将 int 型 3 推送至栈顶(进入finally代码块)
        20: istore_1            //将栈顶 int 型数值存入第二个本地变量(对应finally代码块里的 x=3;)
        21: aload         4     //将第五个 引用 型本地变量推送至栈顶(五号隐式本地变量中暂存的某个隐式异常实例对象的引用存入栈顶)
        23: athrow              //将栈顶的异常抛出
      Exception table:          //【异常表】
         from    to  target type
             0     4     8   Class java/lang/Exception
             0     4    17   any
             8    13    17   any
            17    19    17   any
      LineNumberTable:          //【行号表】
        line 9: 0
        line 10: 2
        line 13: 15
        line 15: 17
        line 16: 21
      StackMapTable: number_of_entries = 2          //栈映射表(也叫栈图、栈图表)
        frame_type = 72 /* same_locals_1_stack_item */
          stack = [ class java/lang/Exception ]
        frame_type = 72 /* same_locals_1_stack_item */
          stack = [ class java/lang/Throwable ]
}
SourceFile: "TestClass.java"

  OpenJDK17.0.8中生成的字节码Code属性的内容与JDK8之前有些变化,不过还是5个局部变量(locals=5),因为 inc() 是实例方法,所以第一个局部变量分配给了指向当前实例的this用!第二个局部变量分配给了显式变量x用,其他变量见Code属性字节码指令的说明!

 

标签:java,字节,OpenJDK17.0,栈顶,样例,int,本地,Utf8,变量
From: https://www.cnblogs.com/xuruiming/p/17659266.html

相关文章

  • 从 Python3.11 新增 SWAP 字节码到基础语法面试题
    点评:典型的送分考验基础的题目,在其他编程语言中可以使用异或运算的方式来实现交换两个变量的值。但是Python中有更为简单明了的Pythonic做法。条件:不允许使用中间变量@目录方法一使用异或(XOR)运算符方法二使用Python的解包特性(元组解包)来交换变量的值元组解包ROT_......
  • BFT最前线|字节跳动AI对话产品“豆包”上线!联想集团推出AI大模型训练服务器!雷尼绍推出
    原创|文BFT机器人AI视界TECHNOLOGYNEWS看点1天才少年稚晖君首秀,官宣智元人形机器人!2023年8月18日上午,从华为离职的“天才少年”彭志辉,也是B站硬核科技UP主稚晖君,公布了他所在的智元团队创业半年的成果——名为“远征A1”的人形机器人。它长得像人,身高175cm,重53kg,可以双足行走,......
  • 两种修改字节码改变函数执行方式
    1示例publicReturnTypefunction(){try{Object[]args=newObject[]{};RetbeforeRet=callOnBefore(args...);//返回对象if(beforeRet.state==1){return(ReturnType)beforeRet.respo......
  • 字节跳动基于DataLeap的DataOps实践
    更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群本文根据ArchSummit全球架构师峰会(深圳站)来自抖音数据研发负责人王洋的现场分享实录整理而成(有删减),本次分享主要包含字节跳动数据研发的模式与挑战、DataOps理念在字节的具象、DataOps产品化......
  • 图片转base64,base64转图片,图片对象转图片字节,图片字节转图片对象
    demo图片转base64defimage_to_base64(image_path):importbase64withopen(image_path,"rb")asimage_file:image_data=image_file.read()base64_encoded=base64.b64encode(image_data).decode("utf-8")retur......
  • 《深入浅出Java虚拟机 — JVM原理与实战》带你攻克技术盲区,夯实底层基础 —— 吃透cla
    前言介绍了解Java代码如何编译成字节码并在JVM上执行是非常重要的。这种理解可以帮助我们理解程序执行时发生的情况,确保语言特性符合逻辑,并在进行讨论时能够全面考虑各种因素和副作用。本文将深入探讨Java代码编译成字节码并在JVM上执行的过程。如果您对JVM的内部结构和字节码执行......
  • 【补充】字符与字节的区别
    在计算机编程中,字符(Character)和字节(Byte)是两个有关数据表示和处理的重要概念。【一】字符(Character):字符代表着某种可视或可打印的符号,例如字母、数字、标点符号、特殊符号等。在计算机内部,字符使用字符编码来表示,最常见的字符编码是ASCII(AmericanStandardCodeforIn......
  • Oracle 12C 新特性-扩展数据类型,在12c中,与早期版本相比,诸如VARCHAR2, NAVARCHAR2以及
    1.查看参数max_string_size默认值SQL>showparametermax_string_sizeNAME                   TYPE                 VALUE---------------------------------------------------------------------......
  • iwebsec-sql注入 06 宽字节字符型注入
    01、题目分析宽字节字符型注入,因为源代码中传参get值的时候,有一个addslashes()函数,是返回在预定义字符('")之前添加反斜杠的字符串。也就是说,当我们按照正常的字符型注入的时候,会在'前加入,也就是说,我们在url上--url写入?id=1'orderby3--+--在addslashes(1'order......
  • AUC计算及为何不受样例不均衡的影响
    在很多排序场景下,尤其是当前许多数据集正负样例都不太均衡;或者说因训练集过大,可能会对数据进行负采样等操作。这擦操作的前提是建立在AUC值不会受到正负样本比例的影响。看过很多博客也都在讨论:为什么AUC不会受正负样例不平衡的影响?为什么排序喜欢选择AUC作为评判指标。一方面,从A......