java - javax.swing.JTabbedPane 不可序列化?
问题描述
当我想反序列化一个 JTabbedPane 时,我得到一个 NullPointerException。
我的代码如下:
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();
}
}
}
当我使用 OpenJDK 运行此代码时89、Ubuntu 20.04 上的 OpenJDK 11 或 Oracle JDK 14.0.1 以及 Win 10(版本 1909)上的 OpenJDK 9 和 Oracle JDK 14,我得到以下或非常相似的堆栈跟踪(这里,我显示了 Oracle JDK 14.0.0 的输出。 1 在 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)
我知道,序列化 Swing 对象是个坏主意。但是,我必须处理的代码大量使用了 Java Swing 的序列化特性。
因此,如果有人能指出我在反序列化 JTabbedPane 时所犯的错误,我将不胜感激。
更新: @GeorgeZ. 的评论让我研究了不同的 JDK 和操作系统:JDK 8在 Ubuntu 20.04(OpenJDK 1.8.0_252 -与我在原始帖子中写的相反)和 Win 10 build 1909(OpenJDK 1.8.0_41)。JDK 9 及更高版本会产生NullPointerException(在 Win10 上:OpenJDK 9 build 9+181 和 Oracle JDK 14.0.1;在 Ubuntu 20.04 上:OpenJDK 9 build 9+181、OpenJDK 11.0.7 和 Oracle JDK 14.0.1)。因此,这似乎是一种回归。
解决方案
目前,JTabbedPane 无法在 JDK 9 和更新版本的 JDK 中反序列化,包括 JDK 15 的早期访问版本。
我提交了一份错误报告,您可以在https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8245785找到该报告。
作为一种解决方法,您可以
- 不序列化 Swing GUI 元素,而只序列化重新创建 GUI 所需的数据模型(正如@DontKnowMuchBut_GettingBetter 指出的那样)或
- 使用 JDK 8(感谢@GeorgeZ 的提示)。
推荐阅读
- flutter - 如何用颤振控制手机亮度
- rust - 带 HashMap 的缓存器
- kotlin - 使用线程池作为调度程序时,延迟()会阻止其协程吗?
- python - 在已知平台(opencv-python)上将对象的位置计算为(x,y)
- postgresql - GCP Cloud SQL Terraform Postgres 扩展
- search - 我可以使用通配符在 Twitter 上搜索主题标签吗
- android - 如何在 Android Wear 上检测夜间睡眠?
- php - Laravel 多对多关系未按预期工作
- phpstorm - WebStorm/PhpStorm:如何禁用特定类型字符串的拼写检查?
- javascript - 如何优化我目前拥有的 JavaScript 代码?