Java 卡中的内存分配
Memory allocation in Java Card
我有一张 Java Card 智能卡,我想评估可用的 EEPROM。
为此,我使用函数 JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT)
。
由于这个函数的return语句是一个short
,没有分配任何数据,我得到了值0x7FFF
。为解决此问题,我以这种方式创建 byte
数组:new byte[(short) 0x7FFF]
以推断可用的持久内存。
如果我创建两个数组:
arr1 = new byte[(short) 0x7FFF];
arr2 = new byte[(short) 0x7FFF];
然后它根据 JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT)
占用 0x1144
字节的可用内存。因此,如果我求和,则意味着有 32767*2 + 4420 = 69954 个字节可用。
但是当我改变数组的大小时:
arr1 = new byte[(short) 0x7FFF];
arr2 = new byte[(short) 0x6FFF];
然后它将占用 0x2244
字节的可用内存。所以如果我求和,这意味着有 70210 个字节可用。
另一个例子:
与
arr1 = new byte[(short) 0x7FFF];
arr2 = new byte[(short) 0x5FFF];
它占用了 0x3344 字节的可用内存。因此,如果我求和,则意味着有 70466 个字节可用。
即使可以忽略不计,为什么会有这些差异?(70210 与 70466 不同)。
同理,我想测试一个小程序可以分配多少个AESKey
。因此,我尝试按照我之前的描述找到可用内存,但使用 AESKey
数组。
使用同一张卡,当我以这种方式创建 AESKey 数组时:
arr = new AESKey[(short) 0x03E8];
for (short i = 0x0000; i < 0x03E8; i++) {
arr[i] = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256, false);
}
所以我创建了一个包含一千个 256 位的数组 AESKey
。我以为需要 32Ko,但是方法 JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT)
表明有 0x0022
字节可用。为什么是这个结果?
如果我用半键测试(例如 500):
arr = new AESKey[(short) 0x01F4];
for (short i = 0x0000; i < 0x01F4; i++) {
arr[i] = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256, false);
}
方法JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT)
表明有0x55EE
(21998)个字节可用:如果可用EEPROM约为70Ko,我绝对看不到与创建1000个密钥的情况的关系就像我在开头解释的那样...
谁能详细说一下Java卡中内存是怎么分配的,来解释上面引用的结果?
嗯,简短的回答:
Java Card 不能巧妙地存储数组/它需要额外的数据。因此,如果您用 x 字节填充字节数组以达到 0x7FFF 阈值,则该数组内部将需要超过 x 字节来存储数据因此,您注意到了差异。
如果您使用的是 JCOP 卡,则可以使用 UtilX.getAvailableMemory()
.
来规避此问题
要了解更多知识,请阅读以下内容:
http://ruimtools.com/doc.php?doc=jc_best关于减少EEPROM消耗的观点(但是有些部分已经过时)
这有几个原因:
- 存在对象分配开销;
- 对齐数据可能会产生开销;
- 内存碎片可能会产生开销;
- 对于密钥,可能会有开销来保证它们的安全。
所有这些问题都会减少您可用的内存量。在这方面,您应该将 getAvailableMemory
视为粗略指示 最大数量 可用内存。
需要多少开销取决于 Java 卡片运行时。
我有一张 Java Card 智能卡,我想评估可用的 EEPROM。
为此,我使用函数 JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT)
。
由于这个函数的return语句是一个short
,没有分配任何数据,我得到了值0x7FFF
。为解决此问题,我以这种方式创建 byte
数组:new byte[(short) 0x7FFF]
以推断可用的持久内存。
如果我创建两个数组:
arr1 = new byte[(short) 0x7FFF];
arr2 = new byte[(short) 0x7FFF];
然后它根据 JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT)
占用 0x1144
字节的可用内存。因此,如果我求和,则意味着有 32767*2 + 4420 = 69954 个字节可用。
但是当我改变数组的大小时:
arr1 = new byte[(short) 0x7FFF];
arr2 = new byte[(short) 0x6FFF];
然后它将占用 0x2244
字节的可用内存。所以如果我求和,这意味着有 70210 个字节可用。
另一个例子: 与
arr1 = new byte[(short) 0x7FFF];
arr2 = new byte[(short) 0x5FFF];
它占用了 0x3344 字节的可用内存。因此,如果我求和,则意味着有 70466 个字节可用。
即使可以忽略不计,为什么会有这些差异?(70210 与 70466 不同)。
同理,我想测试一个小程序可以分配多少个AESKey
。因此,我尝试按照我之前的描述找到可用内存,但使用 AESKey
数组。
使用同一张卡,当我以这种方式创建 AESKey 数组时:
arr = new AESKey[(short) 0x03E8];
for (short i = 0x0000; i < 0x03E8; i++) {
arr[i] = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256, false);
}
所以我创建了一个包含一千个 256 位的数组 AESKey
。我以为需要 32Ko,但是方法 JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT)
表明有 0x0022
字节可用。为什么是这个结果?
如果我用半键测试(例如 500):
arr = new AESKey[(short) 0x01F4];
for (short i = 0x0000; i < 0x01F4; i++) {
arr[i] = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256, false);
}
方法JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT)
表明有0x55EE
(21998)个字节可用:如果可用EEPROM约为70Ko,我绝对看不到与创建1000个密钥的情况的关系就像我在开头解释的那样...
谁能详细说一下Java卡中内存是怎么分配的,来解释上面引用的结果?
嗯,简短的回答:
Java Card 不能巧妙地存储数组/它需要额外的数据。因此,如果您用 x 字节填充字节数组以达到 0x7FFF 阈值,则该数组内部将需要超过 x 字节来存储数据因此,您注意到了差异。
如果您使用的是 JCOP 卡,则可以使用 UtilX.getAvailableMemory()
.
要了解更多知识,请阅读以下内容: http://ruimtools.com/doc.php?doc=jc_best关于减少EEPROM消耗的观点(但是有些部分已经过时)
这有几个原因:
- 存在对象分配开销;
- 对齐数据可能会产生开销;
- 内存碎片可能会产生开销;
- 对于密钥,可能会有开销来保证它们的安全。
所有这些问题都会减少您可用的内存量。在这方面,您应该将 getAvailableMemory
视为粗略指示 最大数量 可用内存。
需要多少开销取决于 Java 卡片运行时。