Forum Stats

  • 3,816,904 Users
  • 2,259,249 Discussions
  • 7,893,591 Comments

Discussions

JC3.0.5 JCSystem.makeGlobalArray() - garbage collection.

User_B9BBH
User_B9BBH Member Posts: 59 Blue Ribbon

The above method allows for the creation of a global buffer similar to the APDU buffer, but the reference to the global buffer can't be cached in instance variables, class variables or array components. I've encountered a few cards where the APDU buffer is only about 271 bytes long. I need to read in an entire 1K sized object and then process it - and I'm doing that often enough that I don't want to create a persistent object. With longer APDU buffers I can use those, but with these tiny 271 byte APDU buffers, I really need a work around.

Let's say I create a 1K global buffer in Applet.process(), pass that reference into a method that receives and processes the entire chunk. When process() returns, I lose my pointer to the buffer.

The question(s): do I need to call JCSystem.requestObjectDeletion() prior to return? Or, is that GC done automatically? E.g. am I going to run out global buffer space by calling the function each time process() is called? Or is something else supposed to happen?

I realize I can use the JCSystem.makeTransient(*)Array calls, but I'd like to avoid tying up RAM space when I don't have to.

Mike

Best Answer

  • patrick.vh-Oracle
    patrick.vh-Oracle Member Posts: 18 Employee
    Answer ✓

    1K is quite large for some cards, so first of all make sure you really can't process it by smaller chunks.

    JCSystem.makeGlobalArray() anyway allocates RAM with the constraint to be used in the current call graph (it's a temporary object which cannot be referenced from a persistent field). The Java Card Runtime Environment should automatically collect corresponding memory at the end of the execution of Applet.process(). This doesn't look appropriate for the use-case you described.

    If you need to store data and use it across sessions or keep data sent via multiple calls to Applet.process, you should instead allocate once a buffer using JCSystem.makeTransient(), with CLEAR_ON_DESELECT to map this memory only when your application is selected, and store the reference to this byte array into a persistent field of your application. If you copy data in this byte[], you will still be able to access it until application is deselected.

Answers

  • patrick.vh-Oracle
    patrick.vh-Oracle Member Posts: 18 Employee
    Answer ✓

    1K is quite large for some cards, so first of all make sure you really can't process it by smaller chunks.

    JCSystem.makeGlobalArray() anyway allocates RAM with the constraint to be used in the current call graph (it's a temporary object which cannot be referenced from a persistent field). The Java Card Runtime Environment should automatically collect corresponding memory at the end of the execution of Applet.process(). This doesn't look appropriate for the use-case you described.

    If you need to store data and use it across sessions or keep data sent via multiple calls to Applet.process, you should instead allocate once a buffer using JCSystem.makeTransient(), with CLEAR_ON_DESELECT to map this memory only when your application is selected, and store the reference to this byte array into a persistent field of your application. If you copy data in this byte[], you will still be able to access it until application is deselected.

  • User_B9BBH
    User_B9BBH Member Posts: 59 Blue Ribbon

    Hi Patrick -

    I'm having to parse an ASN1 ToBeSigned certificate structure and it would be difficult to that on a block by block basis. An older generation of javacard had 1200 byte+ APDU buffers which made things pretty easy. With JC3.0.4 and later, I wanted not to have to depend on having a card with an APDU buffer that large - hence the whole global array question.

    I couldn't find any place in the various specification documents that described the RAM garbage collection, nor its impact on the global array allocation, but what you said makes sense. And I can do all of the sanity checking and extract the longer term data from the global array structure before I return from process().

    I did consider the transient array approach, but there were only a few INSs where I would be dealing with large input buffers, and I didn't want to consume the RAM in case I needed it elsewhere. I do have a few transient scratch pads along with a number of transient keys that are already taking up space.

    Thanks! Mike