【问题标题】:Serializing HashMap with a custom serialized object使用自定义序列化对象序列化 HashMap
【发布时间】:2015-01-27 04:45:56
【问题描述】:

我在 ActionHandler 类中声明了 HashMap:

public class ActionHandler {
    private HashMap<Cooldown, Long> cooldowns = new HashMap<Cooldown, Long>();

    public void disInit(Main main) throws FileNotFoundException, IOException{
        String path = main.getDataFolder() + File.separator + "cooldowns.dat";
        File serialize = new File(path);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(serialize));
        oos.writeObject(cooldowns);
        oos.flush();
        oos.close();
        serialize.createNewFile();
    }
}

 

public class Cooldown implements Serializable{
    private static final long serialVersionUID = 2233153996259053084L;
    private String username;
    private Shop shop;
    public Cooldown(String username, Shop shop){
        //constructing setting the fields...
    }
    public String getUsername(){//returning the fields
    public Shop getShop(){//return shop;}
}

每当插件序列化文件(使用 disInit)时,控制台都会显示此错误。我很兴奋,因为我已经为我的冷却类实现了 Serializable。

[21:16:29 WARN]: java.io.NotSerializableException: com.gmail.ketracoder.vts.Main

[21:16:29 WARN]:        at java.io.ObjectOutputStream.writeObject0(ObjectOutputS
tream.java:1184)
[21:16:29 WARN]:        at java.io.ObjectOutputStream.defaultWriteFields(ObjectO
utputStream.java:1548)
[21:16:29 WARN]:        at java.io.ObjectOutputStream.writeSerialData(ObjectOutp
utStream.java:1509)
[21:16:29 WARN]:        at java.io.ObjectOutputStream.writeOrdinaryObject(Object
OutputStream.java:1432)
[21:16:29 WARN]:        at java.io.ObjectOutputStream.writeObject0(ObjectOutputS
tream.java:1178)
[21:16:29 WARN]:        at java.io.ObjectOutputStream.defaultWriteFields(ObjectO
utputStream.java:1548)
[21:16:29 WARN]:        at java.io.ObjectOutputStream.writeSerialData(ObjectOutp
utStream.java:1509)
[21:16:29 WARN]:        at java.io.ObjectOutputStream.writeOrdinaryObject(Object
OutputStream.java:1432)
[21:16:29 WARN]:        at java.io.ObjectOutputStream.writeObject0(ObjectOutputS
tream.java:1178)
[21:16:29 WARN]:        at java.io.ObjectOutputStream.writeObject(ObjectOutputSt
ream.java:348)
[21:16:29 WARN]:        at java.util.HashMap.internalWriteEntries(HashMap.java:1
776)
[21:16:29 WARN]:        at java.util.HashMap.writeObject(HashMap.java:1354)
[21:16:29 WARN]:        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native M
ethod)
[21:16:29 WARN]:        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMet
hodAccessorImpl.java:62)
[21:16:29 WARN]:        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Deleg
atingMethodAccessorImpl.java:43)
[21:16:29 WARN]:        at java.lang.reflect.Method.invoke(Method.java:483)
[21:16:29 WARN]:        at java.io.ObjectStreamClass.invokeWriteObject(ObjectStr
eamClass.java:988)
[21:16:29 WARN]:        at java.io.ObjectOutputStream.writeSerialData(ObjectOutp
utStream.java:1496)
[21:16:29 WARN]:        at java.io.ObjectOutputStream.writeOrdinaryObject(Object
OutputStream.java:1432)
[21:16:29 WARN]:        at java.io.ObjectOutputStream.writeObject0(ObjectOutputS
tream.java:1178)
[21:16:29 WARN]:        at java.io.ObjectOutputStream.writeObject(ObjectOutputSt
ream.java:348)
[21:16:29 WARN]:        at com.gmail.ketracoder.vts.Shop.ActionHandler.disInit(A
ctionHandler.java:39)
[21:16:29 WARN]:        at com.gmail.ketracoder.vts.Main.onDisable(Main.java:165
)
[21:16:29 WARN]:        at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlug
in.java:323)
[21:16:29 WARN]:        at org.bukkit.plugin.java.JavaPluginLoader.disablePlugin
(JavaPluginLoader.java:359)
[21:16:29 WARN]:        at org.bukkit.plugin.SimplePluginManager.disablePlugin(S
implePluginManager.java:424)
[21:16:29 WARN]:        at org.bukkit.plugin.SimplePluginManager.disablePlugins(
SimplePluginManager.java:417)
[21:16:29 WARN]:        at org.bukkit.craftbukkit.v1_8_R1.CraftServer.disablePlu
gins(CraftServer.java:334)
[21:16:29 WARN]:        at net.minecraft.server.v1_8_R1.MinecraftServer.stop(Min
ecraftServer.java:430)
[21:16:29 WARN]:        at net.minecraft.server.v1_8_R1.MinecraftServer.run(Mine
craftServer.java:561)
[21:16:29 WARN]:        at java.lang.Thread.run(Thread.java:745)

我唯一一次在 HashMap 中放一些东西,就是我打电话的时候:

private void setCooldown(Player player, int slot, Main main, Shop shop){
        String playerName = player.getName();
        Cooldown cooldown = new Cooldown(playerName, shop);
        cooldowns.put(cooldown, System.currentTimeMillis());
}

【问题讨论】:

  • 您的堆栈跟踪中似乎存在问题。您可以尝试重新复制吗?
  • 从控制台复制原样。

标签: java serialization java-8


【解决方案1】:

Cooldown 类是导致问题的原因

不,Main 类是导致问题的原因,正如异常所说:

java.io.NotSerializableException: com.gmail.ketracoder.vts.Main

显然CooldownMain 的内部类,因此它保留了对封闭对象的引用,该对象不可序列化。将其设为静态类或外部类。

NB 在您调用它的地方调用createNewFile() 将产生一个零长度文件。你不需要在任何地方这样做:new FileOutputStream(...) 已经这样做了。只需将其删除。

【讨论】:

  • Cooldown 是一个单独的类,我不确定它是否会导致错误。
  • @NeilDerno 代码不是您在此处表示的,或者它是内部类导致此错误。可能Cooldown 具有对Main显式、非静态非瞬态引用。
  • 我不确定是不是这样,我检查了代码。我发布了一个更好更详细的堆栈跟踪。
  • @NeilDerno 某处是Main 的内部类或明确引用。堆栈跟踪是这样说的。是Shop吗?
  • 先生,您是真正的英雄。 + 1 用于使内部类静态
【解决方案2】:

如果你寻找一个非java.io相关的方法,从最深的stacktrace入口开始,你会发现java.util.HashMap.writeObject负责将对象包含存储在Map中。如果在此过程中遇到像com.gmail.ketracoder.vts.Main 这样的非Serializable 对象,很明显您必须在尝试将其序列化之前将其放入映射中,作为键或值(嗯,或两者兼而有之)。

如果要序列化地图,地图中包含的所有对象都必须是Serializable。不像,例如AWT 组件上的侦听器,不会跳过非Serializable 对象。

但请注意,您所做的事情是危险的。如果Main 的实例包含在映射中,而Main 将依次引用映射(我猜是类名),则您有一个循环引用。虽然序列化原则上适用于循环对象图,但当它们与HashMaps 结合使用时,它将非常脆弱。 HashMap在恢复map时需要rehash所有元素,这可能会导致循环对象图的情况下对不完整的对象调用hashCodeequals

【讨论】:

  • 我唯一一次在 hashmap 中放一些东西是当我打电话时:pastebin.com/cmYPAcZA 另外,我已经更新了 StackTrace 以供将来参考(我使用 JDK 而不是JRE)。
  • 随便你说什么。堆栈跟踪不会说谎;如果它没有被直接包含,它会被你的Cooldown 实例引用为 EJP 已经说过的。如果不是直接引用,那是 Shop 实例引用了 Main
  • 我从来没有听说过你最后一句话中描述的问题。你的来源是什么? “不完整的对象”是什么意思?
  • @EJP:假设您正在恢复一个Main 实例。它包含对HashMap 的引用,因此将恢复此HashMap。这个HashMap 包含对Main 实例的引用,因此它将是对先前在流中看到的实例的反向引用。但此时,Main 实例仍在构建中,可能会丢失正确计算哈希码所需的属性。我从个人经验中知道这个问题,我想,这里有相关的问题;第一个发现:stackoverflow.com/q/10031833/2711488stackoverflow.com/q/7901006/2711488
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-24
  • 2013-08-02
相关资源
最近更新 更多