ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【Java 虚拟机原理】Class 字节码二进制文件分析 七 ( 局部变量表分析 )

2021-09-05 19:58:03  阅读:160  来源: 互联网

标签:lang Java String Utf8 虚拟机 局部变量 Student Class name


文章目录

前言

上一篇博客 【Java 虚拟机原理】Class 字节码二进制文件分析 二 ( 常量池位置 | 常量池结构 | tag | info[] | 完整分析字节码文件中的常量池二进制数据 ) ;





一、编译生成带局部变量表的字节码文件



在 IntelliJ IDEA 中编写如下两个源码 :

Java 类源码 : 在 setName 方法下 , 声明 3 3 3 个局部变量 ;

public class Student {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        int i = 0;
        int j = 1;
        int k = 2;
    }
}

在 main 函数中 创建上述 Student 类对象 : 一定要写这个 main 函数 , 否则虚拟机编译优化时 , 发现 setName 中的局部变量没有使用 , 直接优化掉 , 不生成相关的 局部变量表 ;

public class Main {
    public static void main(String[] args) {
        Student student = new Student();
    }
}

找到上述两个类编译后的字节码文件 : 根据上一篇博客 【Java 虚拟机原理】Class 字节码二进制文件分析 二 ( 常量池位置 | 常量池结构 | tag | info[] | 完整分析字节码文件中的常量池二进制数据 ) 分析 , 常量池是如下选中的区域 ;

在这里插入图片描述

Student.class 字节码文件的附加信息如下 :

Y:\002_WorkSpace\003_IDEA\Demo\out\production\Demo>javap -v Student.class
Classfile /Y:/002_WorkSpace/003_IDEA/Demo/out/production/Demo/Student.class
  Last modified 2021-9-5; size 561 bytes
  MD5 checksum 76a00ba8cb4c4c6aadc52f90e550d7e8
  Compiled from "Student.java"
public class Student
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #4.#24         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#25         // Student.name:Ljava/lang/String;
   #3 = Class              #26            // Student
   #4 = Class              #27            // java/lang/Object
   #5 = Utf8               name
   #6 = Utf8               Ljava/lang/String;
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               LStudent;
  #14 = Utf8               getName
  #15 = Utf8               ()Ljava/lang/String;
  #16 = Utf8               setName
  #17 = Utf8               (Ljava/lang/String;)V
  #18 = Utf8               i
  #19 = Utf8               I
  #20 = Utf8               j
  #21 = Utf8               k
  #22 = Utf8               SourceFile
  #23 = Utf8               Student.java
  #24 = NameAndType        #7:#8          // "<init>":()V
  #25 = NameAndType        #5:#6          // name:Ljava/lang/String;
  #26 = Utf8               Student
  #27 = Utf8               java/lang/Object
{
  public Student();
    descriptor: ()V
    flags: 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 1: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LStudent;

  public java.lang.String getName();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #2                  // Field name:Ljava/lang/String;
         4: areturn
      LineNumberTable:
        line 5: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LStudent;

  public void setName(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=5, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #2                  // Field name:Ljava/lang/String;
         5: iconst_0
         6: istore_2
         7: iconst_1
         8: istore_3
         9: iconst_2
        10: istore        4
        12: return
      LineNumberTable:
        line 9: 0
        line 10: 5
        line 11: 7
        line 12: 9
        line 13: 12
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      13     0  this   LStudent;
            0      13     1  name   Ljava/lang/String;
            7       6     2     i   I
            9       4     3     j   I
           12       1     4     k   I
}
SourceFile: "Student.java"




二、局部变量表



在 Student 的 setName 方法中 , 定义了 3 3 3 个局部变量 , 将 setName 方法的对应字节码的附加信息提取出来单独分析 , 该方法对应的字节码数据中 , 肯定有局部变量表 ;

  public void setName(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=5, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #2                  // Field name:Ljava/lang/String;
         5: iconst_0
         6: istore_2
         7: iconst_1
         8: istore_3
         9: iconst_2
        10: istore        4
        12: return
      LineNumberTable:
        line 9: 0
        line 10: 5
        line 11: 7
        line 12: 9
        line 13: 12
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      13     0  this   LStudent;
            0      13     1  name   Ljava/lang/String;
            7       6     2     i   I
            9       4     3     j   I
           12       1     4     k   I

方法的最后有一个局部变量表 : 该局部变量表就是 " 线程栈 " 中维护的 " 栈帧 " 的 " 局部变量表 " ;

局部变量表 在 编译时 , 就已经在字节码文件中 生成好了 , 在 类加载器 将字节码文件加载到内存中时 , 直接将 字节码中的数据加载到

      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      13     0  this   LStudent;
            0      13     1  name   Ljava/lang/String;
            7       6     2     i   I
            9       4     3     j   I
           12       1     4     k   I

局部变量表的第一行肯定是 局部变量 所在类 ;

局部变量表从 1 1 1 开始计数 , 并不是没有第 0 0 0 个元素 , 第 0 0 0 个元素是当前类 this , 这是所有的局部变量表固定的格式 ;


回顾 【Java 虚拟机原理】垃圾回收算法 ( Java 虚拟机内存分区 | 垃圾回收机制 | 引用计数器算法 | 引用计数循环引用弊端 ) 一、Java 虚拟机内存分区 章节内容 ;

整个 JVM 内存区域分为 方法区 , 堆区 , 线程栈 , 本地方法栈 , 程序计数器 ;

其中 线程栈 中维护 栈帧 , 每个栈帧 中维护 局部变量表 , 操作数栈 , 动态链接 , 方法出口 ; 这里的 局部变量表 就是本博客介绍的 字节码文件 的局部变量表 ;

在这里插入图片描述

标签:lang,Java,String,Utf8,虚拟机,局部变量,Student,Class,name
来源: https://blog.csdn.net/han1202012/article/details/120107764

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有