【问题标题】:Which objects are persistent in Java Card, and when?哪些对象在 Java Card 中是持久的,什么时候持久?
【发布时间】:2018-09-19 21:55:10
【问题描述】:

这个问题是双重的,但希望答案不应该太长,尽管它本身很长。不过,请随意回答其中的一部分,抱歉让其如此详尽!

  • 哪些对象是持久化的?哪些对象是瞬态的?
  • 对象何时持久化?

对于第一部分,问题适用于:

  • 存储在Applet 中的对象
  • 传递存储在Applet 中的对象
  • 仅存储在堆栈变量中的对象(不被任何Applet 引用,甚至是传递性的)
  • 存储在使用makeTransientObjectArray 构建的数组中的对象
  • 传递存储在使用makeTransientObjectArray 构建的数组中的对象(例如,存储在存储在makeTransientObjectArray 中的对象的成员变量中)

对于第二部分,它取决于第一个问题的答案。例如:

  • 我假设直接存储在瞬态对象数组中的对象不会被持久化。在这种情况下,假设堆栈上的对象是持久化的,那么存储在那里的对象什么时候变得不持久化?它是否在new Object 处持久化并且在放入瞬态对象数组时不持久化?
  • 如果一个对象同时具有来自瞬态对象数组和小程序的引用,并且小程序引用被擦除,那么该对象是否未持久化?

提前谢谢你!


我已经查看了 JCRE 规范 v2.2.2(我正在使用的版本),但其中有一些不清楚的地方(因此这个问题很详尽,因为我觉得这更适合 Q/ A式论坛):

  • 第 2-2 页提到,当对象传递存储在 Applet 中时,JCRE 使对象持久化。但是,Glossary-7 声明对象默认是持久的。这种差异似乎无法观察到,但会影响是否需要重新启动卡时是否需要进行垃圾收集。
  • 第 5-1 页指出,瞬态对象的字段绝不能存储在持久内存中。但它没有说明这是否也适用于瞬态对象数组中的传递对象,例如。对象存储在瞬态对象数组的对象字段中。
  • 当一个对象的引用同时存储在瞬态对象数组和Applet 中时,第 5-1 页的相同语句可能与第 2-2 页冲突。

这三个问题分别相当于:

  • 第 1 部分要点 3 和 5(以及,根据答案,第 2 部分要点 1)
  • 第 1 部分要点 5
  • 第 2 部分要点 2

【问题讨论】:

    标签: java smartcard javacard


    【解决方案1】:

    哪些对象是持久化的?哪些对象是瞬态的?

    所有对象实例字段在使用new 创建时都是持久的。 JRE 创建的对象可能不是:您必须查看 Java Card 或 OS 文档才能找到答案。请注意,其他对象的字段是引用。这些引用本身可能指向瞬态内存中的数组或其他包含易失状态的对象。

    如果数组已被创建或定义为瞬态(通常通过调用makeTransientXxxArray()),则它们是瞬态的。它们在使用 new 创建时是持久的。

    对象什么时候被持久化?

    在创建时或任何更新期间。通常,持久值只是简单地放在持久内存中:闪存或 EEPROM。任何对闪存或 EEPROM 的写入都会直接持久化。请注意,Java Card 事务机制仍然可以回滚对持久内存的更改。

    这与 Java SE 非常不同,Java SE 中的对象实例存储在 RAM 中,因此需要在创建和每次更新后进行持久化(如果它们被持久化的话)。

    问: 对于第一部分,问题适用于:...

    不,现在你让它变得不必要的复杂。对象的字段始终保持不变。如何引用它们并不重要。

    引用本身可能不是持久的,即使对象是持久的。例如,它可能位于瞬态对象数组或局部变量中。如果所有引用都丢失,则无法再访问该对象,并且它有资格进行垃圾回收。但在它被收集之前,它仍然会保留在持久内存中。

    我假设直接存储在瞬态对象数组中的对象不会被持久化。在这种情况下,假设堆栈上的对象是持久化的,那么存储在那里的对象什么时候变得不持久化?是否在新对象处持久化,放入瞬态对象数组时不持久化?

    考虑上一个答案。真的没有“瞬态对象数组”这样的东西。存在的是一个由对其他对象的引用组成的数组。这些引用可能是暂时的或持久的。引用的对象可能是瞬态的(数组)或包含对瞬态值的引用。

    对象本身通常不会从持久性转换为瞬态,反之亦然。他们不在乎他们是如何被引用的。他们只关心他们的引用计数是否不为零,因为那样他们就会丢失并且有资格进行垃圾收集。当然,如果它们只是被瞬态对象数组或局部变量中的 volatile 引用引用,则更有可能发生这种情况。

    堆栈本身总是在临时内存中。它包括所有局部变量(包括参数和返回值)。但同样:它不包含任何对象:它可能只包含对堆上的对象瞬态引用。如果这些引用丢失,那么该对象可能会被垃圾回收。


    注意事项:

    • 我这里只说classic Java Card;
    • Java Card 还包含特殊对象,例如 APDU 缓冲区,它有自己的生命周期;
    • 通常您将始终使用持久引用 来指向对象,因为您不希望垃圾收集在 Java Card 上运行,除非在特殊情况下。 - 瞬态数组在重置后被引用时归零。操作系统(应该)确保它们始终可用。
    • 即使有其他小程序可用,CLEAR_ON_RESET 数组也会保留其内容。但是这意味着其他小程序无法重用该临时内存,并且众所周知,小程序内存不足。因此,您应该默认使用CLEAR_ON_DESELECT 瞬态数组,除非上下文切换需要CLEAR_ON_RESET 功能。

    【讨论】:

    • 谢谢!如果我理解正确,这意味着没有办法让自定义对象不保存在磁盘上,因为只有makeTransientXXXArray,没有newTransient 关键字。这意味着每个新对象的创建都会占用垃圾收集空间,即使从未从持久位置引用过……嗯,这有点令人难过。无论如何,谢谢您的准确回答!
    • 你是对的。但是,没有“磁盘”,垃圾收集空间被称为“堆”:) 我有时会和同事开玩笑说添加磁盘、RAM 插槽或主动冷却。
    • 静态字段(类字段)呢?它们是否保存到 nvm 内存中?因此,例如,如果我设置一个静态字节字段 a = 5,然后,重新加载卡,我仍然得到值 5?
    • 是的,当然它们位于 NVM 中(已保存似乎表示特定操作,实际上并非如此)。请注意,通常您应该尝试不要使用 static 字段。请注意,在使用 Java Card 时,private static final 字段实际上是内联到字节码中的。无论您做什么,都不要尝试 update 类字段,更不用说数组了。更新静态存储的数组可能会在 Java Card 上引发一些有趣的问题。对于 Java Card 小程序,您总是有一个对象实例:小程序本身,那么为什么不使用它呢?
    【解决方案2】:

    有一个很好的文档,可以从 oracle.com 免费下载,标题为“Java Card 3 Platform Runtime Environment Specification”

    【讨论】:

    • 我已经搜索了规范,但没有找到我想要的答案。不过,我没有把它放在最初的问题中,因为我觉得这不符合问答格式。我现在更新了我的问题以反映这项研究。希望你能指出我在规范中更精确的地方:)
    猜你喜欢
    • 2013-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多