for循环中的Java Card内存泄漏?

时间:2015-06-03 21:10:45

标签: for-loop memory-leaks javacard

我知道Java Card VM没有垃圾收集器,但for循环会发生什么:

for(short x=0;x<10;x++)
{}

x循环之后是否使用了for变量,还是变成了垃圾?

以防我有一个名为index的瞬态字节数组,大小为2(而不是i循环中的for,我在for循环中使用该数组:

for(index[0]=0;index[0]<10;index[0]++)
{}

但它比第一个版本慢一点。如果我在for循环中对索引使用普通变量,那么它会变得很慢。

那么,第一个x循环中的for变量会发生什么?这样使用for循环是否安全?

2 个答案:

答案 0 :(得分:7)

x变量在字节代码中并不存在。 Java堆栈中的某个位置上有一些操作代表x(无论是Java字节代码还是Java Card转换器转换后的代码)。现在Java堆栈是一个虚拟堆栈。该堆栈在具有寄存器和非虚拟堆栈的CPU上实现。通常,如果有足够的寄存器可用,则变量x只是放在寄存器中,直到它超出范围。寄存器当然可以重复使用。 CPU堆栈本身是瞬态存储器(RAM)中的LIFO(后进先出)队列。在执行构成Applet的字节代码期间,堆栈会不断增长和缩小。与寄存器一样,堆栈存储器一遍又一遍地重复使用。所有局部变量(在代码块内定义的变量以及方法参数)都以这种方式处理。

如果将变量放在瞬态数组中,则将变量放在基于RAM的堆上。 Java Card RAM堆永远不会超出范围。这意味着如果更新需要将更改写入瞬态内存的值。当然,这比通过实验发现的CPU寄存器的本地化更新要慢。通常,瞬态存储器中的存储器永远不会被释放。也就是说,只要您有对数组的引用,您当然可以将内存重用于其他目的。请注意,引用本身(index中的index[0])可能位于持久存储器(EEPROM或闪存)或瞬态存储器中。

目前还不清楚你的意思是什么&#34;正常变量&#34;。如果这是使用new创建的,或者如果它是对象实例中的字段,那么它将持久存储在永久存储器(EEPROM或闪存)中。 EEPROM和闪存具有有限的写周期,写入EEPROM或闪存比写入RAM要快得多

Java Card包含两种瞬态内存:CLEAR_ON_RESET和CLEAR_ON_DESELECT。两者之间的区别在于CLEAR_ON_RESET允许在Applet实例之间共享内存,而CLEAR_ON_DESELECT允许内存由不同的Applet重用。

Java Card classic不包含在Applet执行期间运行的垃圾收集器,您通常只能在启动期间使用JCSystem.requestObjectDeletion()请求垃圾收集,这将清除不再引用的内存,两者都在临时内存中的堆以及持久内存中的堆。清理内存意味着扫描所有内存,标记所有未引用的块,然后压缩内存。这类似于对硬盘进行碎片整理;这可能需要很长时间。

ROM在制造阶段被填满。它可能包含操作系统,Java Card API实现,预加载applet的字节代码(包括常量)等。它只能在字段中读取,因此对所提出的问题没有任何影响。< / p>

答案 1 :(得分:2)

让我们简单介绍一下记忆。简而言之,智能卡中有3种类型的存储器,如下所示:

  • ROM(有时是FLASH)
  • EEPROM
  • RAM

ROM:

卡的操作系统和Java Card API以及此处存储的一些工厂专有包。此内存的内容是固定的,您无法修改它。在这个内存中写入只在芯片生产中发生一次,并且该过程被命名为 Masking

<强> EEPROM:

这是applet加载的可修改内存,它由4个部分组成,如下所示:

  1. 文本:也称为代码段,包含程序的机器指令。代码可以被认为是小说的文本:它讲述了程序的作用
  2. 的故事
  3. 数据:包含程序的静态数据,即程序执行过程中存在的变量。 C或C ++程序中的全局变量是静态的,在C,C ++或Java中声明为static的变量也是如此。
  4. 堆:是用于动态分配内存的内存池,例如C中的malloc()或C ++和Java中的new
  5. Stack:包含系统堆栈,用作临时存储。
  6. 无电(例如卡撕裂)对此内存的内容没有任何影响。

    <强> RAM:

    这也是一种可修改的内存类型。 RAM和EEPROM有三个主要区别:

    1. RAM真的比EEPROM快。 (快1000倍)
    2. RAM的内容将在断电时被破坏。
    3. EEPROM中的写入次数有限(通常为100.000次),而RAM的数量确实更高。
    4. 现在怎么办?

      编写for(short x=0; x<10; x++)时,将x定义为局部变量。局部变量存储在 Stack 中。堆栈指针将在断电时复位,使用的堆栈部分将回收。因此,没有垃圾收集器的主要问题是关于

      ,即使用new关键字定义局部变量时,可以将Heap的一部分指定为局部变量。当运行时环境完成该方法时,该对象将销毁并变为不可用,而Heap的那部分不会被回收。所以你将失去Heap的那部分。您用于for循环的情况似乎没问题,因为您没有使用new关键字,所以没有任何问题。

      请注意,在较新版本的Java Card(2.2.2及更高版本)中,有一个手动垃圾收集器(外观JCSystem.requestObjectDeletion文档)。但是考虑到在某些情况下它确实很慢甚至很危险(看Java Card power less during garbage collection问题)。