0

我编写了一个简单的程序来检查requestObjectDeletion()方法功能和我的卡的可用内存。

我的小程序响应以下五种不同类型的 APDU 命令:

  1. 选择 APDU 命令:响应:0X9000
  2. 命令:XX 00 XX XX XX [...]响应:以字节为单位返回可用内存。
  3. 命令:XX 01 XX XX XX [...]响应:创建一个包含 2000 个元素(即 2000 字节)的本地字节数组。
  4. 命令:XX 02 XX XX XX [...]响应:请求对象删除方法
  5. 其他命令: 响应:0x9000

为了返回可用内存,我编写了一个方法,该方法使用无限while循环创建大量带有100元素的字节数组并counter同时增加 a。捕获Not enough memory异常时,方法返回counter *100(即调用此方法之前的空闲内存)

好的,这是程序:

public class ObjDeletion extends Applet {
    public static short counter = 0x0000;

    private ObjDeletion() {
    }

    public static void install(byte bArray[], short bOffset, byte bLength)
            throws ISOException {
        new ObjDeletion().register();
    }

    public void process(APDU arg0) throws ISOException {

        if (selectingApplet()) {
            return;
        }

        byte[] buffer = arg0.getBuffer();

        switch (buffer[ISO7816.OFFSET_INS]) {
        case 0x00:
            counter=0;
            ReturnAvailableMem();
            break;

        case 0x01:
            genLocalArray();
            break;

        case 0x02:
            JCSystem.requestObjectDeletion();
            break;

        default:
            return;

        }

    }

    public void genLocalArray() {
        byte[] LocalArray = new byte[2000];
    }

    public void ReturnAvailableMem() {
        try {
            while (true) {
                byte[] dump = new byte[100];
                counter += 1;
            }

        } catch (Exception e) {

            ISOException.throwIt((short) (counter * 100));
        }
    }
}

现在,有一个问题。这是当我向卡发送一些 APDU 命令时OpenSC-Tool的输出:

OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000000 -s 00020000
 -s 00000000 -s 00020000 -s 00010000 -s 00000000 -s 00020000 -s 00000000 -s 0002
0000 -s 00010000 -s 00020000 -s 00000000

Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)

//0::returnAvailableMem()
Sending: 00 00 00 00 
Received (SW1=0xE3, SW2=0x58)

//1::returnAvailableMem()
Sending: 00 00 00 00 
Received (SW1=0x00, SW2=0x00)

//2::requestObjectDeletion()
Sending: 00 02 00 00
Received (SW1=0x90, SW2=0x00)

//3::returnAvailableMem()
Sending: 00 00 00 00
Received (SW1=0xE3, SW2=0x58)

//4::requestObjectDeletion()
Sending: 00 02 00 00
Received (SW1=0x90, SW2=0x00)

//5::genLocalArray()
Sending: 00 01 00 00
Received (SW1=0x90, SW2=0x00)

//6::returnAvailableMem()
Sending: 00 00 00 00
Received (SW1=0xDD, SW2=0x18)

//7::requestObjectDeletion()
Sending: 00 02 00 00
Received (SW1=0x90, SW2=0x00)

//8::returnAvailableMem()
Sending: 00 00 00 00
Received (SW1=0xE3, SW2=0x58)

//9::requestObjectDeletion()
Sending: 00 02 00 00
Received (SW1=0x90, SW2=0x00)

//10::genLocalArray()
Sending: 00 01 00 00
Received (SW1=0x90, SW2=0x00)

//11::requestObjectDeletion()
Sending: 00 02 00 00
Received (SW1=0x90, SW2=0x00)

//12::returnAvailableMem()
Sending: 00 00 00 00
Received (SW1=0xE3, SW2=0x58)

命令0返回0xE358(=58200)。所以调用这个方法之前的内存是58200字节。

命令1返回0x0000,这意味着现在可用内存小于100字节。

命令2返回0x9000,所以 requestObjectDeletion 调用成功。

命令再次3返回0xE358,这意味着requestObjectDeletion运行成功。

命令4返回0x9000,所以 requestObjectDeletion 调用成功。

命令5返回,因此现在创建了0x9000一个带有元素的字节数组。2000

现在我希望卡的可用内存等于0xE358 - 2000 = 0xDB88

但在下一个命令中:

命令6返回0xDD18!即我们0xDD18 + 2000 = 0xE4E8的卡中有字节存储空间!

这可能是谁?0xE4E8 - 0xE358为什么卡在第一个命令中看不到这 400 个字节 ( )?

4

1 回答 1

2

答案很简单,因为每个数组(以及其他对象)都需要“标题”来指示其类型、大小等。为此,您需要仔细阅读 JCRE 和 JCVM 规范。

我没有检查“标题”的精确大小,但你可以把它想象成(100 + 'header') * X,而不是简单的100 * X

这也解释了优化技巧:创建一个大数组可以节省更多内存,而不是使用许多小数组——但当然会有一些权衡,比如代码变得不那么可读。

于 2015-04-28T09:29:41.733 回答