Spurious NullPointerException: Cannot invoke "com.objectdb.spi.Tracker.beforeAccess(int)" because "this.__odbTracker" is null

#1

When we use Java serialization for embeddable objects, we spuriously get the following exception:

java.lang.NullPointerException: Cannot invoke "com.objectdb.spi.Tracker.beforeAccess(int)" because "this.__odbTracker" is null
    at quant.phdsc_new.smart_component.label.data.LabelPositionTopRight.writeObject(LabelPositionTopRight.java:1)

We retrieve an object from the database, do a deep copy to ensure any objects with data are fully loaded, and then we enqueue the object to be serialized on another thread. There are some objects which have no data and behave essentially as singletons or custom enums, so we do not copy them, such as LabelPositionTopRight.

ObjectDB Enhancer creates a writeObject method that looks like this:

    private void writeObject(ObjectOutputStream objectOutputStream) throws IOException {
        if (this.__odbTracker != null) {
            this.__odbTracker.beforeAccess(-1);
        }
        objectOutputStream.defaultWriteObject();
    }

At some point, maybe when the original thread closes the connection, the __odbTracker field is set to null.

When Java serialization calls writeObject from another thread at the same time this happens, there is a race condition where __odbTracker is set to null between the "if (this.__odbTracker != null)" condition and the "this.__odbTracker.beforeAccess(-1);" call, causing a NullPointerException.

I have investigated this issue on an old version of ObjectDB, but I didn't see mentions of changes in this area in the release notes, so I don't think the enhanced writeObject method was made thread-safe in a newer version, is that correct?

What would you recommend as a solution? Is there any support for ObjectDB to understand these objects as singletons with no data, such that retrieving them from the database would simply look up the singleton instance, and there would be no need for the Enhancer to make changes since there are no fields? Would it be reasonable to ask for the writeObject enhancement to be made thread-safe, by loading __odbTracker into a variable first, or is the scenario of continuing to use an object after closing the database connection completely unsupported and we would need to change our code to deep clone the singleton while the connection is still open?

Thank you.

Reply