Discussions
Categories
- 196.7K All Categories
- 2.2K Data
- 235 Big Data Appliance
- 1.9K Data Science
- 449.9K Databases
- 221.6K General Database Discussions
- 3.8K Java and JavaScript in the Database
- 31 Multilingual Engine
- 549 MySQL Community Space
- 478 NoSQL Database
- 7.9K Oracle Database Express Edition (XE)
- 3K ORDS, SODA & JSON in the Database
- 532 SQLcl
- 4K SQL Developer Data Modeler
- 186.9K SQL & PL/SQL
- 21.3K SQL Developer
- 295.4K Development
- 17 Developer Projects
- 138 Programming Languages
- 292.1K Development Tools
- 104 DevOps
- 3.1K QA/Testing
- 645.9K Java
- 28 Java Learning Subscription
- 37K Database Connectivity
- 154 Java Community Process
- 105 Java 25
- 22.1K Java APIs
- 138.1K Java Development Tools
- 165.3K Java EE (Java Enterprise Edition)
- 17 Java Essentials
- 158 Java 8 Questions
- 85.9K Java Programming
- 79 Java Puzzle Ball
- 65.1K New To Java
- 1.7K Training / Learning / Certification
- 13.8K Java HotSpot Virtual Machine
- 94.2K Java SE
- 13.8K Java Security
- 203 Java User Groups
- 24 JavaScript - Nashorn
- Programs
- 400 LiveLabs
- 37 Workshops
- 10.2K Software
- 6.7K Berkeley DB Family
- 3.5K JHeadstart
- 5.6K Other Languages
- 2.3K Chinese
- 170 Deutsche Oracle Community
- 1.1K Español
- 1.9K Japanese
- 230 Portuguese
JC3.0.5 JCSystem.makeGlobalArray() - garbage collection.

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
-
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
-
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.
-
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