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. 进入Windows之前发出警告

    实现效果: 知识运用: 通过注册表中HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\子键下的LegalNoticeCaption ...

  2. CentOS启动时自动加载内核模块

    要想在CentOS中自动加载内核模块,需要在/etc/sysconfig/modules/目录中增加一个脚本,在此脚本中加载所需的模块. 下面是我所用的一个名为8021q.modules的脚本,用来在 ...

  3. Framework7:不会Objective-C,也能开发iOS7应用

    摘要:Framework7是一款开源的轻量级HTML框架,用来创建混合或有着iOS7原生体验的Web应用.其包含HTML布局.所有基础界面.动画效果.视图以及简单的自定义样式,让你无需修炼Object ...

  4. C#语句对Access中数据更新问题――Update语法错误

    所有字段最好都用[] 括起来: string sqlUpdate = "update UserInfo set [password] = '" + pass + "',[ ...

  5. C# 常用函数和方法集汇总

    1.DateTime 数字型 System.DateTime currentTime=new System.DateTime(); 1.1 取当前年月日时分秒 currentTime=System.D ...

  6. windows下简单使用pip

    1. 在python官网上下载python时会自带pip,并且在安装Python时若未取消会默认一并安装 2. 找出pip.exe所在位置, 3. 右击此电脑,点击属性 4. 高级系统设置 5. 点击 ...

  7. file_get_contents函数

    今天迁移一个SDK项目到新的机子上,发现项目无法跑起来,报500错误,通过分析,发现原来是file_get_contents函数再作怪,代码如下 public function __construct ...

  8. Linux-WebServer安装和配置

    Apache 基本操作 解释 命令 安装 yum install httpd 启动 service httpd start 停止 service httpd stop 启动完成后 查看进程是否存在:p ...

  9. C语言的位运算的优势 !

    位运算加速技巧1. 如果乘上一个2的倍数数值,可以改用左移运算(Left Shift) 加速 300% x = x * 2; x = x * 64; //改为: x = x << 1; / ...

  10. 单片机入门学习笔记5:STC下载器

    STC下载器主要集成了, 1.芯片识别,下载/编程 2.端口识别 3.串口助手 4.KEIL仿真设置 5.芯片选型 6.范例程序 (集成了定时器,串口等例程) 7.波特率计算器 8.定时器计算器 9. ...