Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How ObjectDeletion works in java card?

Tags:

java

javacard

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?

like image 311
Jean Avatar asked Jul 20 '26 07:07

Jean


1 Answers

First of all, a rule based on my personal experience: if possible, do not use the garbage collector at all. GC is very slow and could be even dangerous (see Javacard - power loss during garbage collection).

Q1: If you really have to use GC, read the documentation:

This method is invoked by the applet to trigger the object deletion service of the Java Card runtime environment. If the Java Card runtime environment implements the object deletion mechanism, the request is merely logged at this time. The Java Card runtime environment must schedule the object deletion service prior to the next invocation of the Applet.process() method.

Shortly speaking, JCSystem.requestObjectDeletion(); has no immediate effect. That is why your local variable oldBuffer remains unchanged.

Q2: To find out how much persistent memory is available to your applet, use:

JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT)

ANSWER to UPDATE 1: JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT) may be confusing for cards with more than 32767 bytes of persistent memory. Such cards usually offer their own proprietary ways to find out available memory.

If the number of available bytes is greater than 32767, then this method returns 32767.

like image 68
vojta Avatar answered Jul 21 '26 21:07

vojta



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!