• JAVA字节码文件之第二篇(常量池)


    一、常量池的内容

    一个java类中定义的很多信息都是由常量池来维护和描述的,可以将常量池看作是class文件的资源仓库,比如java类中定义的方法与变量信息。常量池中主要存储两类常量:字面量(文本字符串,final的常量)与符号引用(类和接口的全限定名,字段的名称和描述符,方法的名称和描述符

    一、常量池的结构

    二、常量池的分析

    常量池(也称常量表):主版本号之后就是常量池的开始位置;java类所对应的常量池主要由常量池数量和常量池数组两部分组成,常量池数量是主版本号之后的两个字节;常量池数组在常量池数量之后,常量池数组中不同元素的类型,结构是不同的,所以该数组长度是不同的,但是数组中的每一种元素的第一个字节是标记位是一个u1类型,JVM在解析常量池时会根据这u1类型来获取元素的具体类型。

    1、常量池元素的数量:

    00 18(24):就是该class字节码文件的常量池数量; 常量池数组元素的个数=常量池数量-1;索引为0的位置暂不使用,目的是满足某些常量池索引值的数据在特定情况下需要表达,不引用任何一个常量池的含义。根本原因是索引为零也是一个常量,只是他不在常量池中,该常量对应null值,所以常量池的索引从1开始(#1)。

     2、常量池数组

    第一个元素:根据Constant pool 中 #1的描述可知该元素是无参的构造函数

    0A(10):常量池元素数量之后的第一个字节,u1=10 对应

     第一个u2(4):占两个字节即00 04;第二个u2(20):占两个字节即00 14;所以该常量池的第一个元素占五个字节即0A 00 04 00 14

    第二个元素:根据 Constant pool  中#2的描述可知该元素是在类ByteCodeTest中一个int 类型 名字为num的变量,

    09(9):第一个元素之后的第一个字节 ,u1=9 对应

     第一个u2(3):占两字节00 03;第二个u2(15):占两个字节00 15;所以该常量池的第二个元素占五个字节即09 00 03 00 15

     第三个元素:根据 Constant pool  中#3 可知该元素是该类的权限定名。

    07(7):第二个元素之后的第一个字节07 ,u1=7 对应

     u2(16):占两个字节00 16;所以该常量池的第三个元素占三个字节即07 00 16

    第四个元素:根据 Constant pool  中#4 可知该元素是该Object类的权限定名。

    07(7):第三个元素之后的第一个字节07 ,u1=7 对应

     u2(17):占两个字节00 17;所以该常量池的第四个元素占三个字节即07 00 17

    第五个元素:根据Constant pool  中#5的描述该元素是字符num

    01(1):第四个元素之后的第一个字节01 ,u1=1 对应

     u2(03):占两个字节00 03,表示utf-8格式的内容对应的长度是3个字节;u1:对应三个字节 6e  75 6d, 所以该常量池的第五个元素占6个字节即01 00 03 6e 75 6d;0x6e756d转字符串=num;

    Hex转字符串工具

    第六个元素:根据Constant pool  中#5的描述该元素是字符I

    01(1):第五个元素之后的第一个字节01 ,u1=1 对应

     u2(01):占两个字节00 01,表示utf-8格式的内容对应的长度是1个字节;u1(73):对应1个字节 49; 所以该常量池的第刘个元素占4个字节即01 00 01 49;49转十进制73;

    根据ASCII字码表可知49=73=I;

    其他元素分析方式与此相同就不再分析,最终分析可知红圈这部分区域是常量池的内容(00 18->63 74)

    三、JVM描述符

    在jvm规范中,每个变量或字段都有描述信息,描述信息主要的作用是描述字段的数据类型,方法的参数列表(包括数量,类型与顺序)与返回值。
    1、为了压缩字节码文件的体积,JVM对于基本数据类型和代表无返回值的void类型都用一个大写字符来表示,而对象类型用字符L加对象的全限定类名来表示
    如下表示:B--byte,C--Char,D--double,F--float,I--int,J--long,S--short,Z--boolean,V--void,L--对象类型如Ljava/lang/String。

    2、对于数组来说,每一个维度使用一个前置的[来表示,如Int[]表示为[I,String[][]表示为[[Ljava/kang/Stirng;

     3、用描述符来描述方法时,用先参数列表后返回值的顺序来描述,参数列表按照参数的严格顺序放在一组()之内,如方法:String getNameById(int id,String name)的描述符为:(I,Ljava/lang/String) Ljava/lang/String;

        public String getNameById(int id,String name){
            return name;
        }

  • 相关阅读:
    Android studio快捷键大全 和 eclipse对照(原)
    .net 提取注释生成API文档 帮助文档
    查看443端口被占用无法启动解决办法
    关于正则表达式 C#
    关于 ImageLoader 说的够细了。。。
    什么时候用Application的Context,什么时候用Activity的Context
    关于layoutparam 请铭记。。。。
    java 静态方法上的泛型
    让多个Fragment 切换时不重新实例化
    开源.net 混淆器ConfuserEx介绍
  • 原文地址:https://www.cnblogs.com/jalja365/p/12152675.html
Copyright © 2020-2023  润新知