javaswingserializationjtabbedpane

javax.swing.JTabbedPane not serializable?


When I want to deserialize a JTabbedPane, I get a NullPointerException.

My code is the following:

import javax.swing.*;
import java.io.*;

public class Bee {

    public static void main(final String[] args) {

        // --------- create tabbed pane
        JTabbedPane tabbedPane = new JTabbedPane();

        // ------------ Test serializing -------------------
        final String file = "/tmp/swing.ser";
        FileOutputStream fout = null;
        ObjectOutputStream out = null;
        FileInputStream fin = null;
        ObjectInputStream oin = null;

        try {
        // ______________________ Write tabbedPane... _______________________
            fout = new FileOutputStream(file);
            out = new ObjectOutputStream(fout);

            out.writeObject(tabbedPane);

            out.close();

            // ____________________________reading pane___________________
            fin = new FileInputStream(file);
            oin = new ObjectInputStream(fin);

            final JTabbedPane readPane = (JTabbedPane) oin.readObject(); 
            System.out.println("readPane: " + readPane.toString());
            oin.close();
            fin.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        } catch (ClassNotFoundException e2) {
            e2.printStackTrace();
        }
    }
}

When I run this code with OpenJDK 8 9, OpenJDK 11 or Oracle JDK 14.0.1 on Ubuntu 20.04 as well as OpenJDK 9 and Oracle JDK 14 on Win 10 (version 1909), I get the following or very similar stacktrace (here, I show the output of Oracle JDK 14.0.1 on Ubuntu 20.04):

Exception in thread "main" java.lang.NullPointerException
at java.desktop/javax.swing.JTabbedPane.getTabCount(JTabbedPane.java:1118)
at java.desktop/javax.swing.plaf.basic.BasicTabbedPaneUI.installTabContainer(BasicTabbedPaneUI.java:308)
at java.desktop/javax.swing.plaf.basic.BasicTabbedPaneUI.installComponents(BasicTabbedPaneUI.java:304)
at java.desktop/javax.swing.plaf.basic.BasicTabbedPaneUI.installUI(BasicTabbedPaneUI.java:248)
at java.desktop/javax.swing.JComponent.setUI(JComponent.java:685)
at java.desktop/javax.swing.JTabbedPane.setUI(JTabbedPane.java:253)
at java.desktop/javax.swing.JTabbedPane.updateUI(JTabbedPane.java:269)
at java.desktop/javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1363)
at java.desktop/javax.swing.SwingUtilities.updateComponentTreeUI(SwingUtilities.java:1354)
at java.desktop/javax.swing.JComponent$ReadObjectCallback.validateObject(JComponent.java:5457)
at java.base/java.io.ObjectInputStream$ValidationList$1.run(ObjectInputStream.java:2758)
at java.base/java.io.ObjectInputStream$ValidationList$1.run(ObjectInputStream.java:2756)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:691)
at java.base/java.io.ObjectInputStream$ValidationList.doCallbacks(ObjectInputStream.java:2754)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:506)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:457)
at Bee.main(Bee.java:31)

I know, it is a bad idea to serialize Swing objects. But, the code I have to work on makes heavy use of the serialization feature of Java Swing.

Thus, I would appreciate if anyone could point me to the mistake I made on deserializing JTabbedPane.

Update: @GeorgeZ.'s comment made me look into different JDKs ans OSs: JDK 8 works without NullPointerException on Ubuntu 20.04 (OpenJDK 1.8.0_252 - contrary to what I've written in my orginal post) and Win 10 build 1909 (OpenJDK 1.8.0_41). JDK 9 and above produces the NullPointerException (on Win10: OpenJDK 9 build 9+181 and Oracle JDK 14.0.1; on Ubuntu 20.04: OpenJDK 9 build 9+181, OpenJDK 11.0.7 and Oracle JDK 14.0.1). Therefore, it seems to be a regression.


Solution

  • Update 9.2.2024: There had been a regression in JDK 9 until JDK 15. In such releases, JTabbedPane could not be deserialized.

    The bug has been fixed in JDK 16. Cf. the bug report at https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8245785.

    In JDK 16 and newer, JTabbedPane can be deserialized.