• JavaCard学习笔记: CAP Component 之 Class Component


    整体结构

    Class Component的紧凑格式和扩展格式结构如下,本篇笔记只记录了紧凑格式的内容。

    class_component_compact { 
    	u1 tag 
    	u2 size 
    	u2 signature_pool_length (since CAP format 2.2)
    	type_descriptor signature_pool[](since CAP format 2.2)
    	interface_info interfaces[] 
    	class_info_compact classes[]
    }
    
    class_component_extended { (since CAP format 2.3)
    	u1 tag 
    	u2 size 
    	u2 signature_pool_length 
    	type_descriptor signature_pool[] 
    	interface_info interfaces[] 
    	class_info_extended classes[]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    tag和size字段

    所有组件开头都是这两个字段,tag表示组件类型,size表示组件大小。

    signature_pool_length和signature_pool

    signature_pool是一个长度为signature_pool_length个字节(注意不是数组元素个数)的type_descriptor类型数组,用以表示远程方法的签名。
    我个人的理解是:在类定义的.java文件中,前面可能会出现类似importXXX的语句,signature_pool数组中的每一项就表示一个导入项的签名,签名的具体内容由【导入类型】+【位置索引】组成。如果导入的是一个方法,签名的具体内容由【导入类型】+【位置token】+【返回类型】组成。

    type_descriptor结构

    type_descriptor的结构定义如下

    type_descriptor { (since CAP format 2.2)
    	u1 nibble_count; 
    	u1 type[(nibble_count+1) / 2]; 
    }
    
    • 1
    • 2
    • 3
    • 4

    导入类型编码

    存在11种导入类型,编码如下。
    在这里插入图片描述

    导入项签名示例

    导入类

    类和方法都属于reference类型。如果package0要导入package1中的c1类,需要6个nibble,该type_descriptor的type占3个字节,具体值如下。
    在这里插入图片描述

    导入数组

    在这里插入图片描述

    导入远程方法

    在这里插入图片描述

    interfaces[]

    表示所有接口的信息,数组中每项用interface_info结构表示单个接口的信息。

    interface_info结构

    interface_info { 
    	u1 bitfield { 
    		bit[4] flags 
    		bit[4] interface_count 
    	} 
    	class_ref superinterfaces[interface_count] 
    	interface_name_info interface_name
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    flags

    这个字段接口和类通用,定义如下:
    在这里插入图片描述
    flags字段的最高位(0x8)置1表示是接口info,置0表示类info。0X4位置1表示共享接口或共享类,0则反之。0x2位置1表示远程接口或远程类,0则反之。

    inteface_count

    表示该接口的父接口数。

    superinterfaces

    一个class_ref类型的数组,存放该接口所有父接口的位置token。

    interface_name

    非远程接口该项为空。
    远程接口,该项的结构如下。interface_name_length表示接口名字的长度,随后就是接口名字的内容, 以UTF-8 格式存放。

    interface_name_info {
    	u1 interface_name_length
    	u1 interface_name[interface_name_length]
    } 
    
    • 1
    • 2
    • 3
    • 4

    class_info_compact classes[]

    表示所有类的信息,紧凑版中每项用class_info_compact结构表示单个类的信息。

    结构

    class_info_compact { 
    	u1 bitfield { 
    		bit[4] flags 
    		bit[4] interface_count 
    	} 
    	class_ref super_class_ref 
    	u1 declared_instance_size 
    	u1 first_reference_token 
    	u1 reference_count 
    	u1 public_method_table_base 
    	u1 public_method_table_count 
    	u1 package_method_table_base 
    	u1 package_method_table_count 
    	u2 public_virtual_method_table[public_method_table_count] 
    	u2 package_virtual_method_table[package_method_table_count] 
    	implemented_interface_info interfaces[interface_count] 
    	remote_interface_info remote_interfaces (since CAP format 2.2)
    	u1 public_virtual_method_token_mapping[public_method_count](since CAP format 2.3)
    	u1 CAP22_inheritable_public_method_token_count(since CAP format 2.3)
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    flags

    这个字段接口和类通用,见上方接口flags描述。

    inteface_count

    表示该类实现的接口数。仅包括该类直接实现的接口数,不包括其父类实现的接口。如下例子中,c0类实现了接口i0,其inteface_count为1;c1类实现了接口i1、i2、i3,其inteface_count为3。注意,c1类没有直接实现i0,接口i0是由其父类c0实现的。

    interface i0 {} 
    interface i1 {} 
    interface i2 extends i1 {} 
    interface i3 {} 
    class c0 implements i0 {} 
    class c1 extends c0 implements i2, i3 {} 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    super_class_ref

    该类的父类。Java仅支持单继承,所以只有一个引用,不是数组。

    declared_instance_size

    类中声明的所有成员变量需要的内存大小,以16位为一个单位。其中,除了int类型的成员变量会占用2个16位,其它类型都只用1个16位。

    first_reference_token

    表示该类第一个引用变量的类型。JavaCard的引用类型有4种,如下图。但我不理解这个字段是用来做什么的= =
    在这里插入图片描述

    reference_count

    表示该类声明的引用类型的成员变量数。

    public_method_table_base

    如果该类有公有虚方法,该项的值为第一个公共虚方法的token值,即接下来的共有虚方法表public_virtual_method_table[public_method_table_count]第一项的token值。
    如果该类无公有虚方法,该项的值为【父类public_method_table_base值】加上【父类public_method_table_count值】。如果该类无父类,则该项值为0.

    public_method_table_count

    public_virtual_method_table的项数。这个字段还有一些细节,待完善,感兴趣的可以自行查阅java智能卡虚拟机规范。

    package_method_table_base

    如果该类有包可见的虚方法(个人理解就是没有static关键字修饰的方法),该项的值为第一个包可见虚方法的token值,即接下来的共有虚方法表package_virtual_method_table[package_method_table_count] 第一项的token值。
    如果该类无包可见虚方法,该项的值为【父类package_method_table_base值】加上【父类package_method_table_count值】。如果该类无父类,则该项值为0.

    package_method_table_count

    package_virtual_method_table的项数。

    public_virtual_method_table[]

    表示该类声明或定义的所有public或protected类型的虚方法,也可能会包含父类声明或定义的方法。数组中的每一项的值代表一个方法在Method组件中相对method_info字段起始地址的偏移量。如果该方法在另一个包里,则该项的偏移量为0xff。

    package_virtual_method_table[package_method_table_count]

    表示所有包内可见的虚方法。个人理解就是没有static关键字修饰的虚方法。其它细节的应以应该可以参考public_virtual_method_table[].

    interfaces[interface_count]

    表示该类直接实现的所有接口的信息。

    implemented_interface_info结构

    implemented_interface_info { 
    	class_ref interface 
    	u1 count 
    	u1 index[count] 
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    interface为接口的引用,count代表接口的实现数量,index中每一项表示一种【实现】的【虚方法】的【token值】。

    remote_interface_info remote_interfaces

    如果前面的flags中,ACC_REMOTE为0,则该字段为空。如果非0,表示这是一个remote接口,remote_interface_info的定义如下

    remote_interface_info { (since CAP format 2.2)
    	u1 remote_methods_count
    	remote_method_info remote_methods[remote_methods_count]
    	u1 hash_modifier_length
    	u1 hash_modifier[hash_modifier_length]
    	u1 class_name_length
    	u1 class_name[class_name_length]
    	u1 remote_interfaces_count
    	class_ref remote_interfaces[remote_interfaces_count] 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    remote_method_info remote_methods[remote_methods_count]

    remote_method_info
    remote_method_info { (since CAP format 2.2)
    	u2 remote_method_hash
    	u2 signature_offset
    	u1 virtual_method_token
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    数组的每一项包含3个信息:

    1. remote方法的哈希值,该值在同一类内是唯一的。
    2. 方法参数的类型定义,即在签名池中的偏移。
    3. 该类的远程方法的虚拟方法token。

    u1 hash_modifier[hash_modifier_length]

    防冲突字符串。相关定义和作用可自行百度。

    u1 class_name[class_name_length]

    顾名思义,这个类的名字。

    class_ref remote_interfaces[remote_interfaces_count]

    每一项都是一个引用,指向一个interface_info结构。

    u1 public_virtual_method_token_mapping[public_method_count]

    方法的token值映射,把【当前类中某个方法的token值】映射到【父类中该方法的token值】。这里可以看出来,虽然是同一个方法,但在父类和子类中的token值可能是不一样的。
    特殊情况:类内定义的方法,映射入参为0xff。
    举个例子,如果类C1是类C2的父类,C1中方法的映射入参为T1,C2中方法的映射入参为T2,那么有以下关系:

    T1=C2.public_virtual_method_token_mapping[T2]
    
    • 1

    CAP22_inheritable_public_method_token_count

    CAP22_inheritable_public_method_token_count项表示由2.2或更早版本的CAP文件中定义的子类可继承的公共或受保护的虚拟方法的数量。

  • 相关阅读:
    跟我学C++中级篇——右值引用和万能引用
    【C刷题】day4
    机器学习从入门到放弃:我们究竟是怎么教会机器自主学习的?
    最优乘车——最短路
    COSCon'22第七届中国开源年会火热筹备中,第一波赞助伙伴已集结,一起上车共赴开源盛宴吧~...
    使用(七牛云)为例子实现将文件上传到云服务器
    声明式事务概念
    解锁横向招聘:创新您的人才搜索
    【Linux多线程服务端编程】| 【05】高效的多线程日志
    JavaWeb-day28_HTML
  • 原文地址:https://blog.csdn.net/Clover_pofu/article/details/137961826