在 Java 中查找不可序列化字段的好方法

2024-02-09

我有一个相当复杂的 Java 对象需要序列化(几周前运行良好)。在同时实现了很多之后,序列化现在失败并抛出以下异常:

java.io.NotSerializableException: sun.java2d.SunGraphics2D

我检查了所有看起来相关的类,但在其中任何一个类中都找不到持有 Graphics2D 类型(或类似类型,如 BufferedImage 等)的字段。在我看来,问题也可能是我使用的类(来自库等)本身是可序列化的,但具有不可序列化类型 Graphics2D 的字段。

所以,我的问题是:有没有一种“好”的方法来找到序列化失败的地方?检查所有类和所做的所有更改似乎几乎不可行。

先感谢您

Lukas

附言。这是异常的完整堆栈跟踪:

java.io.NotSerializableException: sun.java2d.SunGraphics2D
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1378)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
    at java.io.ObjectOutputStream.access$300(ObjectOutputStream.java:162)
    at java.io.ObjectOutputStream$PutFieldImpl.writeFields(ObjectOutputStream.java:1707)
    at java.io.ObjectOutputStream.writeFields(ObjectOutputStream.java:482)
    at java.awt.Container.writeObject(Container.java:3697)
    at sun.reflect.GeneratedMethodAccessor17.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1378)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
    at java.io.ObjectOutputStream.access$300(ObjectOutputStream.java:162)
    at java.io.ObjectOutputStream$PutFieldImpl.writeFields(ObjectOutputStream.java:1707)
    at java.io.ObjectOutputStream.writeFields(ObjectOutputStream.java:482)
    at java.awt.Container.writeObject(Container.java:3697)
    at sun.reflect.GeneratedMethodAccessor17.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1378)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
    at java.io.ObjectOutputStream.access$300(ObjectOutputStream.java:162)
    at java.io.ObjectOutputStream$PutFieldImpl.writeFields(ObjectOutputStream.java:1707)
    at java.io.ObjectOutputStream.writeFields(ObjectOutputStream.java:482)
    at java.awt.Container.writeObject(Container.java:3697)
    at sun.reflect.GeneratedMethodAccessor17.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1378)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
    at java.io.ObjectOutputStream.access$300(ObjectOutputStream.java:162)
    at java.io.ObjectOutputStream$PutFieldImpl.writeFields(ObjectOutputStream.java:1707)
    at java.io.ObjectOutputStream.writeFields(ObjectOutputStream.java:482)
    at java.awt.Container.writeObject(Container.java:3697)
    at sun.reflect.GeneratedMethodAccessor17.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    at java.awt.Window.writeObject(Window.java:2943)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    at java.awt.AWTEventMulticaster.save(AWTEventMulticaster.java:946)
    at java.awt.Window.writeObject(Window.java:2931)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    at java.util.LinkedList.writeObject(LinkedList.java:1131)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    at eas.simulation.SerializableSimulationState.save(SerializableSimulationState.java:121)
    at eas.plugins.standard.visualization.ControlPanel.actionPerformed(ControlPanel.java:202)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2346)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
    at java.awt.Component.processMouseEvent(Component.java:6527)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
    at java.awt.Component.processEvent(Component.java:6292)
    at java.awt.Container.processEvent(Container.java:2234)
    at java.awt.Component.dispatchEventImpl(Component.java:4883)
    at java.awt.Container.dispatchEventImpl(Container.java:2292)
    at java.awt.Component.dispatchEvent(Component.java:4705)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4898)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4533)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4462)
    at java.awt.Container.dispatchEventImpl(Container.java:2278)
    at java.awt.Component.dispatchEvent(Component.java:4705)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:746)
    at java.awt.EventQueue.access$400(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:697)
    at java.awt.EventQueue$3.run(EventQueue.java:691)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.awt.EventQueue$4.run(EventQueue.java:719)
    at java.awt.EventQueue$4.run(EventQueue.java:717)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:716)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

好吧,受到 Ben Lawry 的想法的启发,但他没有提出实际的实现,我还编写了一个类爬虫,它可以查找“不可序列化字段”,即非静态、非瞬态字段,这些字段要么没有实现可序列化接口本身或包含非静态、非瞬态且不实现可序列化接口的字段。

你可以在main方法的列表中添加几个要测试的类(见注释)。输出是来自这些类或任何不能通过上述定义序列化的引用类的字段列表(但是,它并不完全等于实际可序列化字段,而是捕获后者的超集);对于本身实现 Serialized 接口的每个字段,都会给出该字段类型中引用的字段列表,这会导致该字段不可序列化(如果该列表为空,则该字段本身不实现 Serialized 接口)。

这是代码,希望对其他人也有帮助:

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;

import javax.swing.JComponent;

public class Crawler {
    public static boolean crawlRecursively(Field field, HashSet<Class<?>> alreadyCrawled, HashMap<Field, HashSet<String>> badFields) {
        if (alreadyCrawled.contains(field.getType())) {
            return !badFields.keySet().contains(field);
        }

        alreadyCrawled.add(field.getType());

        if (Modifier.isStatic(field.getModifiers())
                || Modifier.isTransient(field.getModifiers())
                || field.getType().isPrimitive()) {
            return true;
        } else if (Serializable.class.isAssignableFrom(field.getType())) {
            boolean allGood = true;

            for (Field f : field.getType().getDeclaredFields()) {
                boolean isGood = crawlRecursively(f, alreadyCrawled, badFields);
                if (!isGood) {
                    if (!badFields.containsKey(field)) {
                        badFields.put(field, new HashSet<>());
                    }
                    badFields.get(field).add(f.getType().getSimpleName() + " " + f.getName());
                    allGood = false;
                }
            }

            return allGood;
        } else {
            if (!badFields.containsKey(field)) {
                badFields.put(field, new HashSet<>());
            }

            return false;
        }
    }

    public static HashMap<Field, HashSet<String>> initiateCrawling(Collection<Class<?>> roots) {
        HashMap<Field, HashSet<String>> badFields = new HashMap<>();

        for (Class<?> root : roots) {
            for (Field f : root.getDeclaredFields()) {
                crawlRecursively(f, new HashSet<>(), badFields);
            }
        }

        return badFields;
    }

    public static void main(String[] args) {
        LinkedList<Class<?>> roots = new LinkedList<>();
        roots.add(JComponent.class); // ADD YOUR CLASSES HERE.
        HashMap<Field, HashSet<String>> badFields = initiateCrawling(roots);

        if (badFields.keySet().size() == 0) {
            System.out.println("All fields are serializable (not having checked the given class(es) themselves).");
        } else {
            System.out.println("The following fields are not serializable in the class tree(s) given by " + roots + ":");
        }

        for (Field field : badFields.keySet()) {
            System.out.println("<UnSer> "
                    + field.getType().getSimpleName() + " " 
                    + field.getName() + " (" 
                    + field.getDeclaringClass().getName() + ") => " + badFields.get(field));
        }
    }
}

JComponent 类的输出示例:

The following fields are not serializable in the class tree(s) given by [class javax.swing.JComponent]:
<UnSer> Border border (javax.swing.JComponent) => []
<UnSer> ComponentInputMap windowInputMap (javax.swing.JComponent) => [JComponent component]
<UnSer> VetoableChangeSupport vetoableChangeSupport (javax.swing.JComponent) => [VetoableChangeListenerMap map, Object source]
<UnSer> SingleSelectionModel selectionModel (javax.swing.JPopupMenu) => []
<UnSer> JPopupMenu popupMenu (javax.swing.JComponent) => [SingleSelectionModel selectionModel]
<UnSer> Object source (java.beans.VetoableChangeSupport) => []
<UnSer> VetoableChangeListenerMap map (java.beans.VetoableChangeSupport) => []
<UnSer> JComponent component (javax.swing.ComponentInputMap) => [VetoableChangeSupport vetoableChangeSupport, JPopupMenu popupMenu, Border border, InputVerifier inputVerifier]
<UnSer> InputVerifier inputVerifier (javax.swing.JComponent) => []
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Java 中查找不可序列化字段的好方法 的相关文章

随机推荐

  • 覆盖 left_join dplyr 来更新数据

    我的问题与此类似 但是我在 LHS 中有其他应保留的列https stackoverflow com a 35642948 9285732 https stackoverflow com a 35642948 9285732 y是一个子集x
  • 角度套接字 io 未定义

    这里有一个建议 https github com btford angular socket io issues 127 https github com btford angular socket io issues 127 确保您有 s
  • 如何使用缓冲区溢出攻击替换堆栈上的返回地址

    对于家庭作业 我正在执行一系列缓冲区溢出攻击 有人给了我一个要反汇编的程序 这是一个不正确调用的函数的 C 源代码gets 以及我应该强制程序调用的其他几个函数的源代码 对于其中一项任务 我必须 注入一些改变值的代码 然后 返回上述方法之一
  • 使用哪个 Java 库来录制连接的摄像机的视频?

    您可能认为有一个简单的解决方案 但没有 我的应用程序需要从 USB 火线 或任何连接 连接的相机捕获流 结果将是一个类似的文件输出 flv 我希望能够检测所有连接的摄像机并选择使用哪一台 同时使用一台或多台 gt 一个或多个输出文件 应用程
  • 不带绑定的验证规则

    我想在文本框上使用 ValidationRules 及其 UI 效果 而不实际将任何内容绑定到文本框 我想将文本框用于某些不绑定到任何内容但需要在焦点丢失后使用 ValidationRules 验证输入的输入 能做到吗
  • 如何创建仅可由特定类使用的构造函数。 (C++ Friend 相当于 C# 中的内容)

    据我所知 在C 中 不象C 中那样支持 friend 关键字 是否有另一种方法来设计一个类 可以实现相同的最终结果 而无需诉诸不可用的 friend 关键字 对于那些还不知道的人来说 Friend 关键字允许程序员指定类 X 的成员只能由类
  • 使用方法在 ArrayList 中循环

    在很多帮助下 我开发了一种方法 可以制作字谜词 然后将它们添加到ArrayList public void f String s String anagram ArrayList
  • 删除崩溃的 Innodb 表

    我无法删除 删除崩溃的 Innodb 表 我收到以下错误 错误 1051 42S02 未知表 帐户 如果我想创建它 我会收到以下错误 错误 1005 HY000 无法创建表 accounts errno 1 我的服务器在意外断电后会发生这种
  • 数 45 秒,暂停 20 秒,然后用不同的标题重复

    在尝试限制电池使用时 我不需要有繁忙的循环 所以我不确定如何解决这个问题 如果我有一个程序 允许某人唱歌 45 秒 然后他们暂停 20 秒喝一杯 然后重复唱一定数量的歌曲 我的计时器是在取消一次迭代并开始另一次迭代后 计时器无法正常工作 h
  • 使用asp.net中的web api通过http进行身份验证

    我观看并浏览了很多有关保护 ASP NET Web API 的页面 包括 http weblogs asp net jgalloway archive 2012 03 23 asp net web api screencast series
  • 为什么 Angular 构建会创建带有“es5”和“es2015”的文件,而不是“es6”(或者根本没有后缀)?

    我最近下载了Angular CLI 角度 cli 9 0 1 然后我继续创建一个新的应用程序 以便我可以创建一个新的 Angular 元素 将其打包并在另一个应用程序中使用它 在关注了几篇博客之后 我遇到的每个博客的最后一步都讨论了从放在
  • 在 Liferay 7 中创建自定义标签库

    我正在使用 Liferay 7 和 OSGi 模块编写一个应用程序 我需要创建一个跨所有模块 portlet 可用的自定义标签库 但我几乎不知道从哪里开始 你有什么主意吗 我应该将 taglib 定义 类和 JSP 存储在 OSGi 模块中
  • Laravel 502 网关错误错误

    我使用 Laravel 5 3 和最新的 Homestead 设置 当我向 API 发出 POST 请求时 根据日志文件 我收到此错误 2016 10 29 12 44 34 错误 776 0 28 recv 失败 104 连接 由对等方重
  • 如何停止正在运行的线程?

    from pyautogui import moveTo click rightClick write keyDown keyUp hotkey scroll import pyautogui import pyperclip import
  • 寻找 IPFW 以外的替代解决方案来减慢互联网连接速度

    我需要减慢 模拟坏的 互联网连接 我发现了一些文档 其中它是通过 ipfw pipeline 命令实现的 问题是在最新的 MAC OS 版本中 ipfw 已被弃用 并删除 我想知道 ipfw API 是否有其他替代方案 有谁知道最新的网络链
  • java 中什么样的全局变量是不好的做法?

    对于我的许多java项目 我广泛使用数据库 我通常做的是有一个property xml文件来保存我所有的字符串和设置 然后我就去上课CNST保存与 xml 文件中的静态常量相对应的所有静态常量 这些常量在程序启动时由 xml 文件初始化一次
  • 如何设置 Rake 任务进行播种

    这确实是一个关于 Rake Rails 以及一般依赖关系的新手问题 尝试让我的头脑了解所有这些如何组合在一起 基本上 我想要一个像 Seed rb 一样但单独调用的 Rake 任务 它添加了开发环境的测试数据 而我的seed rb则提供了所
  • getsockopt IPPROTO_SCTP、SCTP_STATUS 的“无效参数”

    设想 我创建了 SCTP 一对多套接字 以大写字母开头的函数调用相应的标准函数 检查错误并将 errno 打印到 stderr int sock fd msg flags char readbuf BUFFSIZE struct socka
  • DataGridComboBoxColumn 数据绑定

    我正在尝试数据绑定DataGridComboBoxColumn
  • 在 Java 中查找不可序列化字段的好方法

    我有一个相当复杂的 Java 对象需要序列化 几周前运行良好 在同时实现了很多之后 序列化现在失败并抛出以下异常 java io NotSerializableException sun java2d SunGraphics2D 我检查了所