瞬态内存中的 Java Card 对象实例

M.M*_*our 5 java smartcard javacard

我正在开发一个 Java Card 小程序(用于 Java Card 2.2.1),它需要一些临时对象来处理 APDU 命令。我对正确的内存管理有疑问。我花了很多时间研究这些问题,但在某些 Java 卡 API 上没有找到任何说明或好的示例代码。我有两个主要问题:

  1. 如何创建一个瞬态对象数组(我的意思是 RAM 中的自定义对象而不是 EEPROM)。我已经读过,makeTransientObjectArray但它只返回 Object 类型的数组。例如,我知道如何使用 来创建瞬态字节数组makeTransientByteArray,但我的问题是关于对象实例的瞬态数组。或者可以用java语言以任何方式将字节数组转换为没有序列化的实例?

  2. 我只在传入 APDU 命令的过程中需要这个临时对象数组,而不需要保留为我分配的内存。分配这个临时内存的最佳位置在哪里(在install, select, process, ... 函数内)?

编辑以获取更多解释:

  1. 正如我已经从文档中读到的,任何对象实例都存储在 EEPROM 中。假设我知道在我的过程算法中需要的最大对象数(比如 100)。我在 install 方法中生成了 100 个 MyClass 实例。MyClass 的每个实例包含 3 个字段:field1 是一个短类型,field2 是一个字节,field3 是一个短类型。所有这 100 个实例都将通过输入 APDU 命令来填充。如果对于每个命令,我都在 EEPROM 上填充对象,这不是一个好习惯,因为它们是临时数据。EEPROM 也有一个最大的写入周期。一种方法可能是,对于每个实例,我使用makeTransientByteArray和为每个对象分配 5 个字节makeTransientShortArray。但正如我从文档中读到的,它按集群(32 字节 - 不确定大小)分配内存,这是无效的。那么在这种情况下我必须做什么?

  2. 我的意思是如何处理瞬态记忆。如果在安装函数内部分配临时内存,则其他小程序将无法使用它。如果小程序是卡上唯一的小程序,则在install函数中分配所有瞬态内存是一种很好的做法。我想知道一种适用于所有条件(单小程序设备或多小程序设备)的通用有效方法。此外,我不确定,如果在内部分配了瞬态内存install,只要将卡插入读卡器,就可以在进程函数内部使用。

Maa*_*wes 5

不幸的是,在 Java Card 的经典规范中,您尝试做的事情是不可能的。正如您已经注意到的那样,对象实例始终存储在 EEPROM 中。所以你必须解决这个问题。

Java 是一种相对高级的语言,其中对象总是存储在一个特定的内存中。现在他们已将这种类型的内存更改为 Java Card 的持久内存。然而,它需要完全重新设计语言以允许在一种或另一种类型的内存中构造对象。如今,JCF 当然可以考虑为此使用注释——这仍然非常棘手,但可能是可行的。

同样,不可能让对象仅通过一种处理方法存活,即使是数组类型也不行。要实现这一点,您必须有一个附加堆或一个实时垃圾收集器。管理一个堆和向彼此增长的堆栈已经够难的了,实时 GC 也不是当前经典实现中存在的东西。我们在这里工作的环境极其受限。

所以基本上你必须解决平台的限制。


一个好的使用策略是创建一个包含临时内存或引用现有内存(例如 APDU 缓冲区内的内存)的对象的缓存。对象将在安装或个性化期间创建。然后可以在必要时检索这些对象,使用这些对象并将其返回到缓存中。为了给您一个想法,请查看 Java 的ByteBuffer.wrap()方法,该方法允许您对现有数组的一部分执行缓冲区操作。现在考虑该类型的可重用对象。

另一个合乎逻辑的解决方案是根本不使用 OO 编程。嘿,OO 很好很花哨,但我们讨论的是最大内存为 8 到 10 KiB 的芯片。会有限制。用对象可以做的事情通常也可以只用方法来完成(实际上,您可以证明情况确实如此,因为没有对象的 Java 无疑是图灵完备的,但如果您坚持自己的设计,那没什么安慰) .


文字说明:

  • 不,您不能将字节数组转换为对象实例。这将遵循 Java 和 OO 的所有原则。如果可能的话,包括数据封装在内的一切都会被破坏。您当然可以自己反序列化并将结果放入缓存之外的对象中(请参阅上面的策略)。
  • 内存通常应该只在安装或个性化期间分配,或者很可能在使用延迟实例化发布后分配一次。
  • 您不需要 100 个活动对象。您只有少数对象需要在某个特定时间“活着”。利用这些信息!
  • 内存分配特定于平台实现。肯定有“集群”规模较小的平台;平台通常会尝试对齐内存中的数据,因此这也取决于系统/芯片的设计。
  • 使用创建的内存CLEAR_ON_DESELECT可能可供其他小程序使用。如果它们被选中,那么这个 RAM 就不再需要了。一个聪明的实现会将该内存保持在堆的顶部(仍然很棘手,但是嘿)。如上所述,这在选择实例后变得可用。process 方法只会在小程序被选择后被调用(即使是为了处理初始的 SELECT APDU 本身)。