0x01应用场景

获取JavaCard卡内剩余空间,一方面是在评估一张卡的时候需要用到,另一方面是在应用个人化或者运行时需要用到。

例如:应用提供商为了保证自己的应用在卡内运行期间能够不受空间影响,一般会在个人化(安装应用)的时候先分配好需要用到的空间,以免空间被后来应用占用,导致运行失败。

0x02空间类型

卡内剩余空间包括获取卡内的剩余永久存储器(E2P or Flash),还有获取易失性存储器空间(RAM),这里的RAM分为两部分,一部分是在卡片复位时清零的内存CLEAR_ON_RESET,缩写为COR或者RTR(Clear_on_Reset Transient RAM);另一部分为应用在取消选择的时候清零的内存CLEAR_ON_DESELECT,缩写为COD或者DTR(Clear_on_Deselect Transient RAM)。本文将通过实例获取卡内的这三种存储器剩余空间。

0x03获取接口

对于获取JavaCard内可用空间,API提供了相应的接口JCSystem.getAvaliableMemory(byte memoryType) ,位于javacard.framework包下,如下所示,引用自JCAPI v2.2.2。

getAvailableMemory

public static short getAvailableMemory(byte memoryType)
throws SystemException
Obtains the amount of memory of the specified type that is available to the applet. Note that implementation-dependent memory overhead structures may also use the same memory pool.

Notes:

  • The number of bytes returned is only an upper bound on the amount of memory available due to overhead requirements.
  • Allocation of CLEAR_ON_RESET transient objects may affect the amount of CLEAR_ON_DESELECT transient memory available.
  • Allocation of CLEAR_ON_DESELECT transient objects may affect the amount of CLEAR_ON_RESET transient memory available.
  • If the number of available bytes is greater than 32767, then this method returns 32767.
  • The returned count is not an indicator of the size of object which may be created since memory fragmentation is possible.
Parameters:
memoryType - the type of memory being queried. One of the MEMORY_TYPE_* constants defined above. See MEMORY_TYPE_PERSISTENT.
Returns:
the upper bound on available bytes of memory for the specified type
Throws:
SystemException - with the following reason codes:

  • SystemException.ILLEGAL_VALUE if memoryType is not a valid memory type.

根据接口描述,如果可用字节数超过32767(0x3FFF),则只返回32767。那如何返回超过32767的空间,可参考本文后面的代码实例。

0x04代码实例

1.获取DTR剩余空间

     /**
* 获取剩余MEMORY_TYPE_TRANSIENT_DESELECT空间
* @return
*/
public int getFreeDTR(){
//首先取得剩余空间大小
short memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT);
int allmemsize = memsize;
//如果返回值为0x3FFF,则剩余空间大于此值,可继续取得剩余空间
while(memsize == (short)32767){
JCSystem.makeTransientByteArray(memsize,JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT);//不存储返回的数组对象
memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT);
allmemsize += memsize;
}
return allmemsize;
}

 2.获取RTR剩余空间

     /**
* 获取剩余的MEMORY_TYPE_TRANSIENT_RESET空间
* @return
*/
public int getFreeRTR(){
//首先取得剩余空间大小
short memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
int allmemsize = memsize;
//如果返回值为0x3FFF,则剩余空间大于此值,可继续取得剩余空间
while(memsize == (short)32767){
JCSystem.makeTransientByteArray(memsize,JCSystem.MEMORY_TYPE_TRANSIENT_RESET);//不存储返回的数组对象
memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
allmemsize += memsize;
}
return allmemsize;
}

 3.获取E2P/Flash的剩余空间

     /**
* 获取剩余的E2P/Flash空间,如果剩余空间大于0x3FFF,则此接口将创建数组,然后再获取新的剩余空间,
* 数组对象头将占用几个字节(根据对象存储结构不一样,可能占用字节数不同,一般数组头为7字节),因此存在误差。
* @return
*/
public int getFreePersistent(){
//首先取得剩余空间大小
short memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
int allmemsize = memsize;
//如果返回值为0x3FFF,则剩余空间大于此值,可继续取得剩余空间
while(memsize == (short)32767){
byte[] tmp=new byte[memsize]; //不存储返回的数组对象
memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
allmemsize += memsize;
}
return allmemsize;
}

注意

1.获取剩余空间的应用自身的代码需要占用部分空间,本例中的应用代码主468字节,存储在卡内空间为 278 字节.

2.DTR与RTR可能使用同一块区域。

3.以上代码在使用converter转成cap文件时需要加上支持int类型的选项,如果卡片本身不支持int,则代码中相应的地方需要做调整,譬如说如果卡内相应存储器空间大于0x3FFF时,可以将每次取得的值存储在apdubuffer中,一起返回到卡外,然后再计算。

完整代码

 package GetFreeSpacePkg;

 import javacard.framework.APDU;
import javacard.framework.ISO7816;
import javacard.framework.Applet;
import javacard.framework.ISOException;
import javacard.framework.JCSystem; /**
* 获取卡内剩余空间,包括E2P/Flash与RAM.
* 对于E2P/Flash来说,如果卡内剩余空间超过0x3FFF,则此应用返回的数据会有较小的误差。
* 测试命令:
*
* 8000000000 //get DTR
* 8001000000 //get RTR
* 8002000000 //get E2P/Flash
*
* @author SCPlatform@outlook.com
*/
public class GetFreeSpaceApplet extends Applet {
public static void install(byte[] bArray, short bOffset, byte bLength) {
new GetFreeSpaceApplet().register(bArray, (short) (bOffset + 1),bArray[bOffset]);
} public void process(APDU apdu) {
if (selectingApplet()) {
return;
} byte[] buf = apdu.getBuffer();
int iFreeSpace=0;
switch (buf[ISO7816.OFFSET_INS]) {
case (byte) 0x00://DTR
iFreeSpace = getFreeDTR();
break;
case (byte) 0x01://RTR
iFreeSpace = getFreeRTR();
break;
case (byte) 0x02://persistent
iFreeSpace = getFreePersistent();
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
JCSystem.requestObjectDeletion();
buf[3]=(byte)(iFreeSpace);
buf[2]=(byte)(iFreeSpace>>8);
buf[1]=(byte)(iFreeSpace>>16);
buf[0]=(byte)(iFreeSpace>>24);
apdu.setOutgoingAndSend((short)0, (short)4);
}
/**
* 获取剩余MEMORY_TYPE_TRANSIENT_DESELECT空间
* @return
*/
public int getFreeDTR(){
//首先取得剩余空间大小
short memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT);
int allmemsize = memsize;
//如果返回值为0x3FFF,则剩余空间大于此值,可继续取得剩余空间
while(memsize == (short)32767){
JCSystem.makeTransientByteArray(memsize,JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT);//不存储返回的数组对象
memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT);
allmemsize += memsize;
}
return allmemsize;
} /**
* 获取剩余的MEMORY_TYPE_TRANSIENT_RESET空间
* @return
*/
public int getFreeRTR(){
//首先取得剩余空间大小
short memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
int allmemsize = memsize;
//如果返回值为0x3FFF,则剩余空间大于此值,可继续取得剩余空间
while(memsize == (short)32767){
JCSystem.makeTransientByteArray(memsize,JCSystem.MEMORY_TYPE_TRANSIENT_RESET);//不存储返回的数组对象
memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
allmemsize += memsize;
}
return allmemsize;
} /**
* 获取剩余的E2P/Flash空间,如果剩余空间大于0x3FFF,则此接口将创建数组,然后再获取新的剩余空间,
* 数组对象头将占用几个字节(根据对象存储结构不一样,可能占用字节数不同,一般数组头为7字节),因此存在误差。
* @return
*/
public int getFreePersistent(){
//首先取得剩余空间大小
short memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
int allmemsize = memsize;
//如果返回值为0x3FFF,则剩余空间大于此值,可继续取得剩余空间
while(memsize == (short)32767){
byte[] tmp=new byte[memsize]; //不存储返回的数组对象
memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
allmemsize += memsize;
}
return allmemsize;
}
}

0x05资料参考

1.Application Programming Interface Java Card™ Platform, Version 2.2.2

如何获取JavaCard剩余空间的更多相关文章

  1. Linux C++获取磁盘剩余空间和可用空间

    完整源码 #include <sys/statfs.h> #include <string> #include <iostream> #include <li ...

  2. C# 获取磁盘剩余空间

    drive.TotalFreeSpace单位为bit,根据需要除以1024 drive同时可以可以获取磁盘分区容量等 //单位MB public static long GetHardDiskSpac ...

  3. 两种方法,获取磁盘剩余空间--PYTHON

    import ctypes import os import platform import sys def get_free_space_mb(folder): """ ...

  4. C# 获取电脑硬盘剩余空间

    获取本地硬盘的所有剩余空间: 主要应用到System.IO类库的:Driveinfo.Directory,将model转换成json需要用到Newtonsoft.Json.JsonConvert.Se ...

  5. Android中StatFs获取系统/sdcard存储(剩余空间)大小

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...

  6. android计算每个目录剩余空间丶总空间以及SD卡剩余空间

    ublic class MemorySpaceCheck { /** * 计算剩余空间 * @param path * @return */ public static String getAvail ...

  7. Android为TV端助力 计算每个目录剩余空间丶总空间以及SD卡剩余空间

    ublic class MemorySpaceCheck { /** * 计算剩余空间 * @param path * @return */ public static String getAvail ...

  8. c# 读取所有磁盘的剩余空间

    介绍: 有一个控制台命令是创建指定大小的空文件,因此我想制作一个一键填充剩余磁盘空间的坑人小程序. 想要填充剩余容量,就要先获取所有本地磁盘的剩余空间,这个程序就是用来做这个的. 项目类型为c#控制台 ...

  9. SQL Server自动化运维系列——监控磁盘剩余空间及SQL Server错误日志(Power Shell)

    需求描述 在我们的生产环境中,大部分情况下需要有自己的运维体制,包括自己健康状态的检测等.如果发生异常,需要提前预警的,通知形式一般为发邮件告知. 在所有的自检流程中最基础的一个就是磁盘剩余空间检测. ...

随机推荐

  1. 将数据库数据显示到TreeView控件中

    实现效果: 知识运用: TreeView控件中的Nodes集合的Add方法 实现代码: private void init() { treeView1.ShowLines = true; treeVi ...

  2. 2017.12.6 计算机算法分析与设计---------Fibonacci数列

    (1)题目: 无穷数列1,1,2,3,5,8,13,21,34,55,--,称为Fibonacci数列.它可以递归地定义为: 第n个Fibonacci数可递归地计算如下: int fibonacci( ...

  3. python脚本执行报错:SyntaxError: Non-ASCII character '\xe6' in file ip.py on line 4...

    报错信息 [root@chenbj ~]# python ip.py 192.168.1.1 File "ip.py", line 4 SyntaxError: Non-ASCII ...

  4. systemd 中的requires, wants, before, after

    man systemd.unit    man systemd.service ###依赖关系和前后顺序* 依赖关系:Requires和Wants * 前后顺序:After,Before 依赖关系,前 ...

  5. PAT (Basic Level) Practise (中文)- 1002. 写出这个数 (20)

    http://www.patest.cn/contests/pat-b-practise/1002 读入一个自然数n,计算其各位数字之和,用汉语拼音写出和的每一位数字. 输入格式:每个测试输入包含1个 ...

  6. 深入理解React虚拟DOM

    一.什么是虚拟DOM 虚拟DOM可以看做一棵模拟了DOM树的JavaScript对象树.比如: var element = { element: 'ul', props: { id:"uli ...

  7. Centos7 PHP的安装和配置

    前面Nginx和httpd的安装都是为了支持PHP而弄的,然后这个目标就给了我一沉重的打击,等我慢慢道来,先来说说PHP的安装和配置吧. 一.PHP的安装 1.由于linux的yum源不存在php7. ...

  8. 更改 Linux 语言为中文

    查看当前系统语言环境:    echo $LANG 查看安了哪些中文语言包    locale -a |grep "zh_CN" 没有输出,说明没有安装,输入下面的命令安装     ...

  9. FreeRTOS的学习路线

    背景 由于之前接触过一些嵌入式RTOS,如Keil-RTX,uCOS-II,也曾经关注过FreeRTOS,但一直没有机会采用FreeRTOS开发.目前FreeRTOS做为主流RTOS,风声正盛.作为嵌 ...

  10. 【PHP】PHP中的排序函数sort、asort、rsort、krsort、ksort区别分析

    php编程中有时候会需要用上排序,在这里简单地整理一下集中sort的区别,方便查询 sort() 函数用于对数组单元从低到高进行排序. rsort() 函数用于对数组单元从高到低进行排序. asort ...