我知道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
循环是否安全?
答案 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:
卡的操作系统和Java Card API以及此处存储的一些工厂专有包。此内存的内容是固定的,您无法修改它。在这个内存中写入只在芯片生产中发生一次,并且该过程被命名为 Masking 。
<强> EEPROM:强>
这是applet加载的可修改内存,它由4个部分组成,如下所示:
malloc()
或C ++和Java中的new
。无电(例如卡撕裂)对此内存的内容没有任何影响。
<强> RAM:强>
这也是一种可修改的内存类型。 RAM和EEPROM有三个主要区别:
现在怎么办?
编写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问题)。