RFR: 6441373: Editing JTable is not Serializable [v4]

Prasanta Sadhukhan psadhukhan at openjdk.org
Mon Dec 15 06:26:37 UTC 2025


On Thu, 11 Dec 2025 04:45:41 GMT, Prasanta Sadhukhan <psadhukhan at openjdk.org> wrote:

>> Issue is when JTable is in editing mode, it is not Serializable as it gives exception
>> 
>> java.io.NotSerializableException: java.lang.reflect.Constructor
>>         at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1149) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1502)
>>         at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1467)
>>         at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1385)
>>         at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1143) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1502)
>> .......
>> 
>> 
>> It is caused by creation of `GenericEditor` class which uses a non-serializable Constructor field.
>> This is fixed by making the field transient..
>> Also, `editorRemover` field is made transient as it is object of `CellEditorRemover` class which is not Serializable..
>
> Prasanta Sadhukhan has updated the pull request incrementally with one additional commit since the last revision:
> 
>   GenericEditor serialization fix

As I found, the `GenericEditor `is instantiated and stored as `Object `class in `defaultEditorsByColumnClass `field. So, it seems when `ObjectOutputStream.writeObject` is called, `GenericEditor `is getting serialized as it implements Serializable. `defaultEditorsByColumnClass `is transient so that field will be skipped when the parent JTable object is serialized however, the items stored inside the Hashtable are still objects that exist in memory. The issue is that the standard Java serialization mechanism might still find and serialize the GenericEditor instances through other, less obvious references that Swing creates i.e The transient keyword hides your initial map reference, but doesn't prevent the object from being serialized if reached via other paths.`
defaultEditorsByColumnClass`  uses a `UIDefaults.LazyValue`. This lazy value doesn't create the GenericEditor immediately; it stores a function (a lambda expression) that creates one when `createValue(t)` is called.
The key point is that JTable or the Swing look-and-feel code eventually calls this lazy value to get the actual GenericEditor instance when it needs a default editor. The created GenericEditor instance is then likely stored in an another internal, non-transient field within the JTable or a related UI delegate object.
When you serialize a JTable, Swing's serialization process involves
    JTable itself implements Serializable.
    It has an internal field for a tableHeader.
    It has a ui field (the UI delegate, e.g., BasicTableUI), which also manages aspects of the table's appearance and behavior, including editors.

When we initialize the JTable and it prepares its default editors, it creates instances of those editors. The JTable keeps a strong, non-transient reference to the actual GenericEditor instance via its internal machinery (likely through the TableCellEditor storage mechanism).
Even if  the custom hashtable reference is transient, the built-in Swing fields that now hold the reference to the GenericEditor instance are not transient and participate in the standard serialization process

I tried having GenericEditor implement Externalizable to have control of the GenericEditor serialization process so that GenericEditor doesn't participate in the serialization process and override writeExternal, readExternal. 
Also, readObject() seems to install UI again which is done anyway in writeObject (as is usually done for other classes) which is also removed. 
Also, In writeObject(), cell editing is stopped as all editor related fields are transient but something still retains the reference to JTextField..

-------------

PR Comment: https://git.openjdk.org/jdk/pull/28627#issuecomment-3653588080


More information about the client-libs-dev mailing list