MQ

MQ

Join this online group to communicate across IBM product users and experts by sharing advice and best practices with peers and staying up to date regarding product enhancements.

 View Only

IBM MQ Classes for JMS removal of "finalize()" implementation

By Jack Burden posted Tue April 15, 2025 06:17 AM

  

Introduction

Firstly, it is worth explaining the original intended purpose of the finalize method within the Java specification. It is called implicitly by the Java Virtual Machine when it has determined all references to that specific object have left usable scope. To quote the specification...

Called by the garbage collector on an object when garbage collection determines that there are no more references to the object. A subclass overrides the finalize method to dispose of system resources or to perform other cleanup.

More detail can be found here

What did IBM MQ use the finalize method for?

The IBM MQ Classes for JMS (Java Message Service) employed the finalize method for cleanup of resources where appropriate, and most notably for cleanup of the JmqiWorkerThread objects. These JmqiWorkerThread objects are most commonly created when a BINDINGs connection is used, as opposed to TCP/IP. However, the JmqiWorkerThread can also be employed, through use of specific Java system properties, when a TCP/IP connection is used. The worker threads are used for asynchronous MQ API work, such as MQCONN, MQGET etc. 

Now, when a JMS Connection object is created, for example by calling MQQueueConnection.createConnection(...), a JmqiWorkerThread object (and thread) would be spawned to service the MQAPI calls occurring on that Connection object (provided the aforementioned pre-requisites are met). Once the Connection object had gone out of "scope", i.e. the Java Garbage Collector had deemed no usable references remained, the finalize method implementation would be called, resulting in the JmqiWorkerThread objects being tidied (through use of join etc). This in-turn would prevent any JmqiWorkerThread objects from being leaked, which over the time-span of a long running application, would prevent significant heap usage and indeed potential OutOfMemory exceptions.

Why did IBM MQ remove the finalize functionality from their Java client offerings?

The reasoning for the removal and change in behaviour is two-fold...

  1. The Java specification have officially deprecated the finalize method since version 9.
  2. The IBM MQ Java client offerings moved towards Java 17 with the release of 9.2.4 CD (and hence 9.3 LTS) onwards.

As for point [1], here is the official Java specification reasoning for deprecation...

Deprecated. The finalization mechanism is inherently problematic. Finalization can lead to performance issues, deadlocks, and hangs. Errors in finalizers can lead to resource leaks; there is no way to cancel finalization if it is no longer necessary; and no ordering is specified among calls to finalize methods of different objects. Furthermore, there are no guarantees regarding the timing of finalization. The finalize method might be called on a finalizable object only after an indefinite delay, if at all. Classes whose instances hold non-heap resources should provide a method to enable explicit release of those resources, and they should also implement AutoCloseable if appropriate. The Cleaner and PhantomReference provide more flexible and efficient ways to release resources when an object becomes unreachable.

As for point [2], from an IBM MQ perspective we are required to move forward with our Java implementation support, i.e. Java 17+. This inherently means, since it is complex to maintain two sources, that we are required to remove our implementation of the finalize method as of course it would no longer compile with Java 17.

Furthermore, the finalize functionality should never be relied upon anyway, and the IBM MQ implementation was always only intended as a potential fail-safe in the unlikely event, and contrary to JMS specification, that a client application fails to explicitly call close on a JMS Connection object.

For reference, here is an excerpt of the JMS Connection object specification...

Since a provider typically allocates significant resources outside the JVM on behalf of a connection, clients should close these resources when they are not needed. Relying on garbage collection to eventually reclaim these resources may not be timely enough.

More details can be found here.

So, how does this affect you and your client application(s)?

If you have IBM MQ Classes for JMS reliant client applications in your workload, utilising a version at or later than 9.2.4 CD, then you might experience increased heap usage and potential OutOfMemory exceptions in the JVM. As explained above, this is potentially caused by an oversight in failing to call close on JMS Connection objects before they go out of scope, ultimately resulting in leaked JmqiWorkerThread objects.

The solution is to check your application code carefully, analysing all potential code paths, and ensuring that close is always explicitly called, as per the JMS specification, on suitable JMS objects.

0 comments
14 views

Permalink