NullPointerException when serializing TableModel
See original GitHub issueHi,
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.
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.SwingUtilities;
import javax.swing.WindowConstants;
import com.formdev.flatlaf.FlatDarkLaf;
public class Serialization {
public static void main(String[] args) throws Exception {
FlatDarkLaf.setup(); // When using FlatLaf, it causes a NullPointer when serializing.
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
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
frame.add(table);
frame.setSize(300,300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
});
Thread.sleep(1000); // For GUI to finish building, fixes initial NullPointer
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("some.dat"));
oos.writeObject(model);
oos.close();
System.out.println("Done");
}
}
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("A");
list.add("B");
list.add("C");
}
@Override
public int getRowCount() {
return list.size();
}
@Override
public int getColumnCount() {
return 1;
}
@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
}
}
This is the Stacktrace I got.
Exception in thread “AWT-EventQueue-0” java.lang.NullPointerException: Cannot invoke “javax.swing.CellRendererPane.paintComponent(java.awt.Graphics, java.awt.Component, java.awt.Container, int, int, int, int, boolean)” because “this.rendererPane” is null at java.desktop/javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:2191) at java.desktop/javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:2092) at java.desktop/javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1888) at com.formdev.flatlaf.ui.FlatTableUI.paint(FlatTableUI.java:397) at java.desktop/javax.swing.plaf.ComponentUI.update(ComponentUI.java:161) at java.desktop/javax.swing.JComponent.paintComponent(JComponent.java:797) at java.desktop/javax.swing.JComponent.paint(JComponent.java:1074) at java.desktop/javax.swing.JComponent.paintToOffscreen(JComponent.java:5255) at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBufferedImpl(RepaintManager.java:1643) at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1618) at java.desktop/javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1556) at java.desktop/javax.swing.RepaintManager.paint(RepaintManager.java:1323) at java.desktop/javax.swing.JComponent._paintImmediately(JComponent.java:5203) at java.desktop/javax.swing.JComponent.paintImmediately(JComponent.java:5013) at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:865) at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:848) at java.base/java.security.AccessController.doPrivileged(AccessController.java:391) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85) at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:848) at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:823) at java.desktop/javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:772) at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1884) at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:316) at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770) 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.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740) 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.validate(Container.java:1657) at java.desktop/javax.swing.RepaintManager$3.run(RepaintManager.java:745) at java.desktop/javax.swing.RepaintManager$3.run(RepaintManager.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/javax.swing.RepaintManager.validateInvalidComponents(RepaintManager.java:742) at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1883) at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:316) at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770) 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.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740) 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:101) at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90) Done
Issue Analytics
- State:
- Created a year ago
- Comments:5
yes
This is a threading issue.
You should not serialize Swing objects on the main thread. Always do it on the AWT thread. Then it works.
But this also serializes the
JTable
(and maybe the complete component hierarchy) because the table adds a listener to the model. So there is a reference from the model to the table…I would avoid serialization of table model. Better serialize a custom object.