Below, you see a program that I wrote to see the state of different fields and memory allocations after calling requestObjectDeletion()
method:
public class ReqObjDel extends Applet {
static byte[] buffer = new byte[2];
static boolean isNull = false;
private ReqObjDel() {
}
public static void install(byte bArray[], short bOffset, byte bLength)
throws ISOException {
new ReqObjDel().register();
}
public void process(APDU arg0) throws ISOException {
if (selectingApplet()) {
return;
}
if (buffer != null && (short) buffer.length == (short) 10) {
return;
}
byte[] oldBuffer = buffer;
buffer = new byte[10];
JCSystem.requestObjectDeletion();
if (oldBuffer == null)
isNull = true;
if (isNull) {
ISOException.throwIt((short) 0x1111);
} else
ISOException.throwIt((short) 0x0000);
}
}
As far as I know,this method reclaims memory which is being used by “unreachable” objects. To be “unreachable”, an object can neither be pointed to by a static field nor by an object field. So calling requestObjectDeletion()
in the above program reclaims the part of EEPROM that oldBuffer
is refer to (As far as I know, oldBuffer
is neither class field nor object field,right?). In this situation I expect that oldBuffer == null
and therefore the JCRE must return 0x1111
. But the output is 0x0000
unexpectedly :
OSC: opensc-tool -s 00a404000b0102030405060708090000 -s 00000000
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 00 00
Received (SW1=0x00, SW2=0x00)
Q1 : What can I conclude?
- That part of memory is not reclaimed?
- That part of memory is reclaimed but
oldBuffer
is a reference to it still? - something else?
Q2 : Is there any way to obtain the free memory size before and after of calling this method? (i.e. is there any method that return the size of free memory[not allocated]?)
Update 1 : Trying JCSystem.getAvailableMemory()
Based on @vojta answer, I changed my program in a way that the line byte[] oldBuffer = buffer;
runs only once (using a flag named isFirstInvocation
) and return the free available memory in two consecutive process()
method invocation :
public class ReqObjDel extends Applet {
static byte[] buffer = new byte[10];
static boolean isFirstInvocation = true;
private ReqObjDel() {
}
public static void install(byte bArray[], short bOffset, byte bLength)
throws ISOException {
new ReqObjDel().register();
}
public void process(APDU arg0) throws ISOException {
if (selectingApplet()) {
return;
}
short availableMem1 = JCSystem
.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
if (isFirstInvocation) {
byte[] oldBuffer = buffer;
buffer = new byte[10];
JCSystem.requestObjectDeletion();
firstInvocation = false;
}
short availableMem2 = JCSystem
.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
short availableMemory = (short) (availableMem1 + availableMem2);
ISOException.throwIt(availableMemory);
}
}
And this is the output :
OSC: osc -s 00a404000b0102030405060708090000 -s 00000000 -s 00000000
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 00 00
Received (SW1=0xFF, SW2=0xFE)
Sending: 00 00 00 00
Received (SW1=0xFF, SW2=0xFE)
As both invocations return an equal value, I think the JCRE reclaims that part of memory immediately after calling requestObjectDeletion()
, right?