学弟学妹们,如果你想吃透 Java字节码的话,看这篇就好了!(超级硬核,建议收藏3)

简介: 学弟学妹们,如果你想吃透 Java字节码的话,看这篇就好了!(超级硬核,建议收藏)

04、字段表集合


字段表用来描述接口或者类中声明的变量,包括类变量和成员变量,但不包含声明在方法中局部变量。


字段的修饰符一般有:


访问权限修饰符,比如 public private protected

静态变量修饰符,比如 static

final 修饰符

并发可见性修饰符,比如 volatile

序列化修饰符,比如 transient

然后是字段的类型(可以是基本数据类型、数组和对象)和名称。


在 Main.class 字节码文件中,字段表的信息如下所示。


private int age;

   descriptor: I

   flags: (0x0002) ACC_PRIVATE



表明字段的访问权限修饰符为 private,类型为 int,名称为 age。


字段的访问标志和类的访问标志非常类似。



image.png


05、方法表集合


方法表用来描述接口或者类中声明的方法,包括类方法和成员方法,以及构造方法。方法的修饰符和字段略有不同,比如说 volatile 和 transient 不能用来修饰方法,再比如说方法的修饰符多了 synchronized、native、strictfp 和 abstract。


image.png


下面这部分为构造方法,返回类型为 void,访问标志为 public。


 public com.itwanger.jvm.Main();

   descriptor: ()V

   flags: (0x0001) ACC_PUBLIC


来详细看一下其中 Code 属性。


 

Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: bipush        18
         7: putfield      #2                  // Field age:I
        10: return
      LineNumberTable:
        line 6: 0
        line 7: 4
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      11     0  this   Lcom/itwanger/jvm/Main;



stack 为最大操作数栈,Java 虚拟机在运行的时候会根据这个值来分配栈帧的操作数栈深度。


locals 为局部变量所需要的存储空间,单位为槽(slot),方法的参数变量和方法内的局部变量都会存储在局部变量表中。


args_size 为方法的参数个数。


为什么 stack 的值为 2,locals 的值为 1,args_size 的值为 1 呢? 默认的构造方法不是没有参数和局部变量吗?


这是因为有一个隐藏的 this 变量,只要不是静态方法,都会有一个当前类的对象 this 悄悄的存在着。这就解释了为什么 locals 和 args_size 的值为 1 的问题。那为什么 stack 的值为 2 呢?因为字节码指令 invokespecial(调用父类的构造方法进行初始化)会消耗掉一个当前类的引用,所以 aload_0 执行了 2 次,也就意味着操作数栈的大小为 2。


关于字节码指令,我们后面再详细介绍。


LineNumberTable,该属性的作用是描述源码行号与字节码行号(字节码偏移量)之间的对应关系。


LocalVariableTable,该属性的作用是描述帧栈中的局部变量与源码中定义的变量之间的关系。大家仔细看一下,就能看到 this 的影子了。


下面这部分为成员方法 getAge(),返回类型为 int,访问标志为 public。


 public int getAge();

   descriptor: ()I

   flags: (0x0001) ACC_PUBLIC


理解了构造方法的 Code 属性后,再看 getAge() 方法的 Code 属性时,就很容易理解了。


 

Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #2                  // Field age:I
         4: ireturn
      LineNumberTable:
        line 9: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/itwanger/jvm/Main;



最大操作数栈为 1,局部变量所需要的存储空间为 1,方法的参数个数为 1,是因为局部变量只有一个隐藏的 this,并且字节码指令中只执行了一次 aload_0。


本来想着这一篇就彻底把 Java 字节码给结束掉,没想到还得再学习一下字节码指令,难顶!


其实学习就是这样,可以横向扩展,也可以纵向扩展。当我们初学编程的时候,特别想多学一点,属于横向扩展,当有了一定的编程经验后,想更上一层楼,就需要纵向扩展,不断深入地学,连根拔起,从而形成自己的知识体系。


无论是从十六进制的字节码角度,还是 jclasslib 图形化查看反编译后的字节码的角度,也或者是今天这样从 javap 反编译后的角度,都能窥探出一些新的内容来!


初学者一开始接触字节码的时候会感觉比较头大,没关系,我当初也是这样,随着时间的推移,经验的积累,慢慢就好了,越往深处钻,就越能体会到那种“技术我有,雄霸天下”的感觉~


说两句,马上秋招了,可以开始准备了。


一定记得刷一刷面试题,背一背八股文,要乖哦,千万不要抗拒!千万不要裸面,真的!其实私下里,很多学弟学妹们都向我哭诉过,说大厂的面试题太难了,有的题出的真的是万万没想到啊(狗头)。甚至有些中小厂的面试题都很难对答如流(他们的面试官可能看过我这份面试题库,哈哈哈),有了这份面试题库后,大家再也不用慌了!


V4.0 《JavaGuide 面试突击版》来啦!GitHub 上标星 98.1k,帮你成功上岸!


我是一直在悄悄打怪的二哥,希望能和同学们一起,变得更强,更秃(不不不,更帅),既然看到着了,就赏个三连吧,只收藏也不是不可以!


下期见~


相关文章
|
3月前
|
安全 Java API
JDK 11中的动态类文件常量:探索Java字节码的灵活性与动态性
在JDK 11中,Java语言引入了一个新的特性,允许在运行时动态地修改类文件常量。这一特性为Java开发者提供了更大的灵活性,使他们能够根据需要在运行时更改类文件中的常量值。本文将深入探讨动态类文件常量的工作原理、优点、限制以及在实际项目中的应用。
49 11
|
8月前
|
Oracle Java 编译器
Java 中如何生成字节码?
Java 中如何生成字节码?
|
8月前
|
前端开发 Java 编译器
Java 字节码
Java 字节码
29 1
|
2天前
|
存储 安全 Java
深入理解Java字节码与反编译技术
深入理解Java字节码与反编译技术
10 0
|
2月前
|
缓存 Java 计算机视觉
深入理解Java自动装箱和自动拆箱(反编译字节码理解每条指令)
在Java中,自动装箱(Autoboxing)是指将基本数据类型(如int、char等)自动转换为其对应的包装类(如Integer、Character等)的过程。而自动拆箱(Unboxing)则是将包装类的对象转换回其对应的基本数据类型的操作。这些特性从Java SE 5开始被引入,以方便开发者在处理基本类型和其包装类之间进行转换。 下面是一个简短的摘要: - **自动装箱**:当基本类型赋值给包装类时,例如 `Integer i = 1;`,Java会自动调用Integer的`valueOf()`方法,将int转换为Integer对象。对于数值在-128到127之间的int,会使用Int
46 2
深入理解Java自动装箱和自动拆箱(反编译字节码理解每条指令)
|
2月前
|
存储 Java 索引
《深入浅出Java虚拟机 — JVM原理与实战》带你攻克技术盲区,夯实底层基础 —— 吃透class字节码文件技术基底和实现原理(核心结构剖析)
《深入浅出Java虚拟机 — JVM原理与实战》带你攻克技术盲区,夯实底层基础 —— 吃透class字节码文件技术基底和实现原理(核心结构剖析)
34 0
|
6月前
|
安全 算法 Java
从零开发基于ASM字节码的Java代码混淆插件XHood
因在公司负责基础框架的开发设计,所以针对框架源代码的保护工作比较重视,之前也加入了一系列保护措施,例如自定义classloader加密保护,授权license保护等,但都是防君子不防小人,安全等级还比较低,经过调研各类加密混淆措施后,决定自研混淆插件,自主可控,能够贴合实际情况进行定制化,达到框架升级后使用零感知,零影响
74 1
从零开发基于ASM字节码的Java代码混淆插件XHood
|
3月前
|
缓存 监控 Java
Javaassist:编写字节码,改变Java的命运
Javaassist:编写字节码,改变Java的命运
33 0
|
4月前
|
Java
Idea如何方便的查看Java字节码文件😁
Idea如何方便的查看Java字节码文件😁
59 0
|
5月前
|
Java Windows
查看java文件汇编代码与字节码
查看java文件汇编代码与字节码
50 0