Revew Proposal for transactional aware GC

Calvin Smith calvinrsmith at
Fri Jun 2 16:20:00 UTC 2017

TransactionGC: Less GC for Transactional Systems

Similar to proposal: JEP draft: Epsilon GC: The Arbitrarily Low Overhead Garbage (Non-)Collector


Start as normal and run with the chosen garbage collector. A class/method may be registered and once it starts to run and until the method exits all memory is allocated in a thread local allocation buffer and is not available for other threads. In addition there is no garbage collection for these objects during this time. Once the buffer is exhausted then an OutOfMemory will be raised and the stack unwind


When running in a request / response transaction environment do not collect objects created during the transaction.


There is no goal to require any special Java code. The same code should work with or without this feature.


When running in a request / response transaction environment there may be a need to create a lot of objects, however, none of these objects are required after the transaction has completed and if the transaction is short enough (single digit milliseconds) any garbage collection at all will delay the system. Some of this can be mitigated by carefully tracing and being aware of the objects that are created, however, due to presence of third-party code (some of which may be built into the JDK) this is not always possible.


Standard JDK by default; enabled with special option: -XX:+UseTransactionGC.

With this option the JDK works as normal until a given configured method is invoked. Once invoked all future allocations from that point on, on that thread, until the method exits is different. All allocations occur in a thread local allocation buffer where an allocation is simply updating a pointer to account for the allocation. There is no garbage tracking or collection within this method. Instead the memory buffer gets more filled up with each allocation. Once the method exits then the pointer is updated again to be reset at the place it was at the start of the method, thus de-allocating all the objects at one time.

The goal is to avoid a GC pause to collect objects created during a transaction. A global GC may still run and may pause the thread. As there is no GC of this buffer all of the objects created during the transaction must fit within the TLAB at one time.

Issues to solve / be aware of when the configured method is executing:

* Any memory allocated may only be referenced by other objects also created during this time. For example a cache created before the method starts may not access any of these objects

* Any memory allocated may only be referenced by the allocating thread.

* Any attempt to break the prior two rules will result in a VM error

* Due to first two rules there is no need for GC to occur, the memory may be de-allocated simply by setting the TLAB pointer back to it's original location.

* finalize must be called on these objects prior to de-alloction, however, execution of the finalize must still honor the first two rules.

* Any uncaught exceptions that pass out of the method must be moved prior to de-allocation such that the exception is no longer in the area to be cleared. Furthermore, any references that the exception contains must also be moved.

* Any exception thrown and caught during this time it may be treated like any other object and will be de-allocated at the exit of the method.

* If an object that is created in this method is required to be referenced from the outside then it must be created outside the method. Once such way is to place the data for the object on a queue and have a background thread process the queue and create the object. Adding to the queue must not create any objects or the background thread cannot access them. Instead pre-allocated entries may be used.

* The objects will still show up during a heap dump, perhaps they can be marked in some fashion to make it easier to recognize that they are not GC'able objects.

* JNI. Any JNI call cannot access the created objects after the method has ended.

Further enhancements:

* Synchronization - As none of the objects created in this mode can be accessed by other threads there is no need for synchronization, so all synchronization can be removed / stubbed out.


Some of this may be done without changing the JVM and instead using a Java agent. When the method is invoked the classes referenced are re-transformed and the methods of the referenced classes are converted to static, all objects are created as bytes in a byte array. All field references are updated to read / write this byte array. Then an object reference is just a number which is an index into the array. Then when an instance method is invoked two extra parameters are passed a) the byte array b) the index into the byte array that is the start of the instance

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the hotspot-gc-dev mailing list