gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-11-01 01:26:10 24 4
gpt4 key购买 nike

我有一个非常复杂的 Java 对象要序列化(几周前运行良好)。在此期间实现了很多之后,序列化现在无法抛出以下异常:

java.io.NotSerializableException: sun.java2d.SunGraphics2D

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

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

提前致谢

卢卡斯

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

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 的启发,但他没有提出实际的实现,我还编写了一个类爬虫程序,它可以找到“不可序列化的字段”,即非静态、非 transient 字段本身未实现 Serializable 接口(interface)或包含非静态、非 transient 且未实现 Serializable 接口(interface)的字段。

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

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

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) => []

关于java - 在 Java 中查找不可序列化字段的好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25074673/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com