Reputation: 87
I declare the HashMap, inside the ActionHandler class:
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;}
}
The console spits out this error whenever the plugin serializes the file (with disInit). I am stoked because I am already implementing Serializable for my cooldowns class.
[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)
The only time I put something in the HashMap, is when I call:
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());
}
Upvotes: 0
Views: 1968
Reputation: 298143
If you look for a non-java.io
related method, starting from the deepest stacktrace entry, you will find java.util.HashMap.writeObject
which is responsible for storing the objects contained in the Map
. If a non-Serializable
object like com.gmail.ketracoder.vts.Main
is encountered during this process, it’s clear that you must have put it into the map before your attempt to serialize it, either as a key or a value (well, or both).
If you want to serialize a map, all objects contained in the map must be Serializable
. Unlike, e.g. listeners on AWT components, there is no skipping of non-Serializable
objects.
But note that what you are doing is dangerous. If an instance of Main
is contained in the map while Main
will, in turn, have a reference to the map (I guess that from the class name), you have a cyclic reference. While Serialization works in principle with cyclic object graphs, it will be very fragile when these are combined with HashMap
s. The HashMap
needs to rehash all elements when restoring the map, which may cause hashCode
and equals
invoked on incomplete objects in the case of cyclic object graphs.
Upvotes: 1
Reputation: 310884
The
Cooldown
class is what is causing the problem
No, the Main
class is what is causing the problem, as the exception says:
java.io.NotSerializableException: com.gmail.ketracoder.vts.Main
Clearly Cooldown
is an inner class of Main
, so it retains a reference to the enclosing object, which isn't serializable. Make it a static class, or an outer class.
NB calling createNewFile()
in the place where you call it will yield a zero length file. You don't need to do that anywhere: new FileOutputStream(...)
already does that. Just remove it.
Upvotes: 2