Java NullPointerException on serialization of TableModel when associated JTable is on visible JFrame

268 views Asked by At

A NullPointerException is thrown when trying to serialize a TableModel object while the associated JTable object is visible in a JFrame. I created a minimal, reproducible Example and will also include the Stack-Trace.

The Nullpointer is described like this:

Cannot invoke "javax.swing.JTable.getColumnModel()" 
because "this.table" is null

But why is this method called anyway? I am serializing the Model, not the JTable.

When not using a JFrame, it works fine.

I hope someone can help. I am using AdoptOpenJDK14 (14.0.2.12-hotspot)

Here is the minimal, reproducible Example:

Serialization.java (Entrypoint of the Program)

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.WindowConstants;

public class Serialization {

    public static void main(String[] args) throws Exception {

        MyAbstractModel model = new MyAbstractModel();
        JTable table = new JTable(model);

        // After creating the frame, putting in the table and setting it to visible the exception will be thrown when trying to serialize below
        JFrame frame = new JFrame();
        frame.add(table);
        frame.setSize(300,300);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setVisible(true);

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("some.dat"));
        oos.writeObject(model);
        oos.close();

    }
}

MyAbstractModel.java (The Model to Serialize)

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.table.AbstractTableModel;

public class MyAbstractModel extends AbstractTableModel {

    private List<String> list = new ArrayList<>();

    public MyAbstractModel(){
        list = Collections.synchronizedList(new ArrayList<>());
        list.add("Test1");
        list.add("Test2");
        list.add("Test3");
        list.add("Test4");
    }

    @Override
    public int getRowCount() {
        return 10;
    }

    @Override
    public int getColumnCount() {
        return 3;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        return rowIndex + "-" + columnIndex;
    }

    @Override
    public String getColumnName(int column) {
        return "Column " + column;
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return String.class;
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return false;
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        // TODO
    }
}

Some.java (Just a Serializable Test Object)

import java.io.Serializable;

public class Some implements Serializable {

    private static final long serialVersionUID = 1L;

    public final int num;
    public final String name;
    transient int ignoreNum;

    public Some(int num, String name, int ignoreNum) {
        this.num = num;
        this.name = name;
        this.ignoreNum = ignoreNum;
    }

    @Override
    public String toString() {
        return "Some{" +
                "num=" + num +
                ", name='" + name + '\'' +
                ", ignoreNum=" + ignoreNum +
                '}';
    }

}

This is the Stacktrace I got.

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: Cannot invoke "javax.swing.JTable.getColumnModel()" because "this.table" is null at java.desktop/javax.swing.plaf.basic.BasicTableUI.getPreferredSize(BasicTableUI.java:1768) at java.desktop/javax.swing.JComponent.getPreferredSize(JComponent.java:1680) at java.desktop/javax.swing.JTable.setWidthsFromPreferredWidths(JTable.java:3205) at java.desktop/javax.swing.JTable.doLayout(JTable.java:3117) at java.desktop/java.awt.Container.validateTree(Container.java:1722) at java.desktop/java.awt.Container.validateTree(Container.java:1731) at java.desktop/java.awt.Container.validateTree(Container.java:1731) at java.desktop/java.awt.Container.validateTree(Container.java:1731) at java.desktop/java.awt.Container.validateTree(Container.java:1731) at java.desktop/java.awt.Container.validate(Container.java:1657) at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2762) at java.desktop/java.awt.Component.dispatchEvent(Component.java:4844) at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:772) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715) at java.base/java.security.AccessController.doPrivileged(AccessController.java:391) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:95) at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745) at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:743) at java.base/java.security.AccessController.doPrivileged(AccessController.java:391) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85) at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742) at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203) at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124) at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90) Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: Cannot invoke "javax.swing.JTable.getColumnModel()" because "this.table" is null
at java.desktop/javax.swing.plaf.basic.BasicTableUI.getPreferredSize(BasicTableUI.java:1768) at java.desktop/javax.swing.JComponent.getPreferredSize(JComponent.java:1680) at java.desktop/javax.swing.JTable.setWidthsFromPreferredWidths(JTable.java:3205) at java.desktop/javax.swing.JTable.doLayout(JTable.java:3117) at java.desktop/java.awt.Container.validateTree(Container.java:1722) at java.desktop/java.awt.Container.validateTree(Container.java:1731) at java.desktop/java.awt.Container.validateTree(Container.java:1731) at java.desktop/java.awt.Container.validateTree(Container.java:1731) at java.desktop/java.awt.Container.validateTree(Container.java:1731) at java.desktop/java.awt.Container.validate(Container.java:1657) at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2762) at java.desktop/java.awt.Component.dispatchEvent(Component.java:4844) at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:772) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715) at java.base/java.security.AccessController.doPrivileged(AccessController.java:391) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:95) at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745) at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:743) at java.base/java.security.AccessController.doPrivileged(AccessController.java:391) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85) at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742) at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203) at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124) at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

0

There are 0 answers