JavaCard Object删除及垃圾回收设计

--by Caesar

对象的存储:

对象以Heap的方式统一管理,ref以索引方式读取定长的Heap头。

永久对象:HeapBody存储在NVM中,并以TLV的方式连接。Heap头存储指向HeapBody的偏移。

临时对象:HeapBody为预置的全局数组。Heap头不存储偏移,偏移由索引前的所有临时对象的空间的和计算得出。由于获取偏移的计算量比较大,所以使用Cache的方式来加速(见附录1)

对象的删除:

永久对象:删除Heap头。并删除指向的HeapBody,如果待删的HeapBody前后都有空块,则自动合并成为一个大空块。

临时对象:删除Heap头。全局数组对应偏移的数据,自动向前移动对象长度个字节。

垃圾回收操作:

系统可以调用JCSystem.isObjectDeletionSupported 和JCSystem.requestObjectDeletion 进行运行态的垃圾回收请求。

垃圾对象的定义:

在Java环境中,垃圾对象指的是未被有效对象引用的对象。在JavaCard环境里面,有效对象被定义为如下几种对象:

1.JCRE系统对象。

2.指明不能被垃圾回收的普通对象。

3.包的static image对象。

4.应用的instance实例对象。

5.Java运行栈和临时变量区中的引用类型变量指向的对象。

6.被以上几种对象直接或者间接引用的对象。

凡是不符合以上有效对象描述的对象,都被称为垃圾对象。

对象引用关系的遍历:

基于对垃圾对象的描述,可以看到,如果要做垃圾回收,必须先确定所有的有效对象。由于分析运行栈内数据类型比较困难,所以我们通常选择在Java运行栈为空的时候启动垃圾回收。由于对象的引用关系是深层和交叉的,所以无法用固定维度的循环来处理。遍历的逻辑为:

1.申请一个大缓存空间,每个对象的引用对应两个bit的标志位。初始为00.

2.遍历全部的pkg索引,获得对应的static image的对象引用,并将对应的标志位设置为10.

3.遍历全部的app索引,获得对应的instance实例对象引用,并将对应的标志位设置为10.

4.遍历全部的obj索引,获得所有表明不能垃圾回收的对象的引用,并将对应的标志位设置为10.

5.循环遍历缓冲区,找到所有标志位为10对应的对象,获得该对象直接引用的所有对象的引用(见附录2),并将对应的标志设置为1X。之后将自己的标志位设置成11。持续循环,直到再也找不到标志位为10的对象。

6.当前缓冲区内,标志位为11的对象即为有效对象,标志位为00的对象即为垃圾对象。可以以此为基础进行进一步的处理。

其中第一标志位代表对象的有效性,第二标志位代表对象的引用关系是否已经展开。以上的逻辑就是设置有效对象的根节点,然后全部展开。循环结束的标志为找不到10意味着,没有有效对象没有被展开了。

其中1-4对应方法:bool MMGC_ObjMap_Init(P_FRAM(U08) mapbuf, U16 maplen)

其中5对应方法:void MMGC_ObjMap_Traverse(P_FRAM(U08) mapbuf)

其中6对应方法:bool MMGC_ObjMap_Operate(U08 u8Scope, U08 u8Condition, U08 u8OpType, P_FRAM(U08) mapbuf, HEAPREF ref)

垃圾回收过程:

可以看到,垃圾回收的实现:当用户程序调用API试图垃圾回收的时候,系统不马上操作(运行栈不为空),而是记录flg。直到下次process入口点方法执行之前,判断flg,重置flag,并依照以上的步骤,进行对象的删除。

    if(g_bGCFlag && VMFRAME_ISEMPTY())

    {

g_bGCFlag = false;

MMGC_ObjMap_Init(g_pau8TempBuf,MMOBJ_TEMP_BUF_SIZE);

MMGC_ObjMap_Traverse(g_pau8TempBuf);

MMGC_ObjMap_Operate(MMGC_OP_SCOPE_NOTIN_MAP, MMGC_OP_CONDITION_NONE, MMGC_OP_TYPE_DEL, g_pau8TempBuf, MM_REF_NULL);

}

应用的删除:

在用户调用GlobalPlatform的delete命令试图删除一个应用的时候,首先要判断在所有的逻辑通道内,该应用是否为激活状态,然后就要做依赖性判断,原则就是该应用的任何对象(ObjectOwner=thisApp)均不能被其它应用的对象直接或者间接的引用。或者被包的static image直接或者间接的引用。(安全域作为特殊的应用,依赖关系过于复杂,不建议支持删除)

结合垃圾回收过程,该过程的逻辑相似。只需要在第四步之后,将该app对应的instance实例对象和AID对象重置为00。即从有效对象中删除该app的入口点对象和关联的JCRE对象。遍历之后,判断有效对象中是否存在该应用的对象。如果不存在,证明该应用的对象没有被其它的有效对象直接或者间接的引用,可以删除。反之,不能删除。而删除的过程和垃圾回收一样,删除所有状态位为00的无效对象就可以了。注意,AID作为关联的JCRE对象,不参与引用关系判断,但是参与回收。如下:

MMGC_ObjMap_Init(apdu_buffer, SYSTP_ISO_APDU_BUFFER_SIZE);

            MMGC_ObjMap_ResetApp(apdu_buffer, arApp);

            MMGC_ObjMap_Traverse(apdu_buffer);

//ref by other object

            if(MMGC_ObjMap_Operate(MMGC_OP_SCOPE_IN_MAP, MMGC_OP_CONDITION_OWNER_EQ, MMGC_OP_TYPE_RET, apdu_buffer, arApp))

            {

                SysExcp_ThrowISO(ISO_SW_CONDITIONS_NOT_SATISFIED);

            }

            //delete appref

            SYSReg_Delete(arApp);

            //delete all obj of app

MMGC_ObjMap_Operate(MMGC_OP_SCOPE_NOTIN_MAP, MMGC_OP_CONDITION_NONE, MMGC_OP_TYPE_DEL, apdu_buffer, MM_REF_NULL);

包的删除:

在用户调用GlobalPlatform的delete命令试图删除一个包的时候,首先要判断在所有的逻辑通道内,属于该包的应用是否为激活状态,该包是否被其它的包显式的import。然后就要做依赖性判断,原则就是该包的任何对象(Context=thisPkg)均不能被其它包应用的对象直接或者间接的引用。或者被其它包的static image直接或者间接的引用。

结合垃圾回收和应用删除过程,该过程的逻辑相似。只需要在第四步之后,将该pkg对应的static image对象以及所有应用的instance实例对象和AID对象重置为00。即从有效对象中删除该pkg的入口点对象和关联的JCRE对象。遍历之后,判断有效对象中是否存在该包的对象。如果不存在,证明该应用的对象没有被其它的有效对象直接或者间接的引用,可以删除。反之,不能删除。而删除的过程和垃圾回收一样,删除所有状态位为00的无效对象就可以了。注意,AID作为关联的JCRE对象,不参与引用关系判断,但是参与回收。如下:

//perform dependency checks

MMGC_ObjMap_Init(apdu_buffer, SYSTP_ISO_APDU_BUFFER_SIZE);

//

MMGC_ObjMap_ResetPkg(apdu_buffer, prPkg, (bool)(iso_p2==0x80));

//

MMGC_ObjMap_Traverse(apdu_buffer);

if(MMGC_ObjMap_Operate(MMGC_OP_SCOPE_IN_MAP, MMGC_OP_CONDITION_CONTEXT_EQ, MMGC_OP_TYPE_RET, apdu_buffer, prPkg))

{

SysExcp_ThrowISO(ISO_SW_CONDITIONS_NOT_SATISFIED);

}

if(iso_p2 == 0x80)

{

//delete appref

DeleteAppInPkg(prPkg);

}

//delete pkgref

MMHeap_Delete(prPkg);

//delete all package objectMMGC_ObjMap_Operate(MMGC_OP_SCOPE_NOTIN_MAP, MMGC_OP_CONDITION_NONE, MMGC_OP_TYPE_DEL, apdu_buffer, MM_REF_NULL);

空间的管理策略:

鉴于永久对象的存储方式,不适合进行大规模的搬移整理。系统的最大下载能力不是所有空块的空间总和,而是以HeapBody的最大TLV块为限制的。所以要谨防空间的碎片化。空间的碎片化有如下几种情况产生。

用户行为中的交叉下载和删除操作:

用户下载包A,包B,删除A,就将导致包B分割了两个空块,最大空间将不再是 Max-B。

系统行为中的对象:

用户下载包A,运行A的应用过程在调用API的时候产生了JCRE系统对象。(比 如某些static ref),删除A。这个系统对象将分割两个空块,最大空间将不再是Max。

我们无法控制用户行为,只能尽量减少API运行时产生对象。无field的对象则无此限制。并建议用户在大规模下载之前,最好删除所有的应用和包,并重新下载和安装。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值