Edit, Here's how i solved using the comments
So after trying different ways of serializing and looking through my code, I finally found out that each object drawn in the renderer contains FloatBuffers. I created a capsule class thanks to Ted Hopp. Then I tried returning the float representation of the FloatBuffers using .array(), which you can't do. My guess is because these are running on threads. So using a suggestion from Learn OpenGL ES to use get, i instead did
public float[] getVertexBuffer()
{
float[] local = new float[vertexBuffer.capacity()];
vertexBuffer.get(local);
return local;
}
Which does work and returns the float[].
Then i store them all in a capsule object for each mGrid object i created
Encapsulate capsule = new Encapsulate(values);
for(int i = 0; i < values[0]; i++)
{
for(int j = 0; j < values[1]; j++)
{
capsule.storeVertex(i,j,mRenderer.mGrid[i*values[1] + j].getVertexBuffer());
capsule.storeColors(i,j,mRenderer.mGrid[i*values[1] + j].getmColors());
capsule.storePillar(i,j,mRenderer.mGrid[i*values[1] + j].getPillarPositions());
}
}
Which I can then ultimately save because it's serializable. Thank you all
PROBLEM DESCRIPTION
So i'm trying to save a GLSurfaceView object, whose class is denoted as
class GLWorld extends GLSurfaceView implements Serializable
Now I'm sure as i do the saving correctly.
public void saveSimulation()
{
String fileName = "Test Save";
try {
FileOutputStream fos = openFileOutput(fileName, Context.MODE_PRIVATE);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(mGLView);
Log.d("Save","Successfully Written");
oos.close();
fos.close();
} catch (FileNotFoundException e) {
Log.d("Save","File not found exception");
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
Log.d("Save","IO exception");
// TODO Auto-generated catch block
e.printStackTrace();
}
finish();
}
But i'm getting an error i have no clue how to fix. I've spent hours looking around but haven't found anything like it.
09-16 17:36:50.639: W/System.err(2996): java.io.NotSerializableException: java.nio.FloatToByteBufferAdapter
Along with many more system err lines below that, which i believe stem from this one error.
My GLWorld creates a renderer object in it which has different objects with floatbuffers in it which store vertex and color data. I can't figure out what to do to get past this error, or why those float buffers are throwing an error. Everything runs smoothly except actually trying to save this GLWorld object and it's driving me insane.
Just declaring that a class implements Serializable is not enough to successfully serialize objects of that class. The default implementation requires that every field of the class be serializable. In your case, there's a field of type FloatToByteBufferAdapter that isn't serializable (there may be more).
You can define your own serialization mechanism to serialize only what you need. The details can be found in the Serializable docs. Be aware that by subclassing GLSurfaceView, it is unlikely you will be able to successfully deserialize this class, even if you write the correct support methods. For one thing, GLSurfaceView does not have a default (no-arg) constructor, which is a requirement of Java's serialization mechanism. Also, many objects simply cannot be serialized (e.g., streams).
I suggest that you encapsulate the data you want to serialize in a helper class and limit the serialization/deserialization to those data.
Gotta assume that something within the mGLView inheritance contains FloatTOByteBufferAdapter, which isn't serializable.
Related
I am currently in need to serialize arbitrary Java objects since I would like to use the Hash as a key for a hash table. After I read various warnings that the default hashCode creates collisions way to often, I wanted to switch to hashing via MessageDigest to use alternative algorithms (e.g. SHA1, ...) that are said to allow more entries without collisions. [As a sidenote: I am aware that even here collisions can occur early on, yet I want to increase the likelihood to remain collision free.]
To achieve this I tried a method proposed in this StackOverflow post. It uses the following code to obtain a byte[] necessary for MessageDigest:
public static byte[] convertToHashableByteArray(Object obj) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
byte[] byteOutput = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(obj);
byteOutput = bos.toByteArray();
} catch (IOException io) {
io.printStackTrace();
} finally {
try {
if(out != null) { out.close(); }
} catch(IOException io) {
io.printStackTrace();
}
try {
bos.close();
} catch(IOException io) {
io.printStackTrace();
}
}
return byteOutput;
}
This, however, causes the problem that only objects implementing the serializable interface will be serialized/converted into a byte[]. To circumvent this issue I applied toString() to the given obj in the catch clause to enforce getting a byte[] in all cases:
public static byte[] convertToHashableByteArray(Object obj) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
byte[] byteOutput = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(obj);
byteOutput = bos.toByteArray();
} catch (IOException io) {
String stringed = obj.toString();
byteOutput = stringed.getBytes();
} finally {
try {
if(out != null) { out.close(); }
} catch(IOException io) {
io.printStackTrace();
}
try {
bos.close();
} catch(IOException io) {
io.printStackTrace();
}
}
return byteOutput;
}
However, this still feels utterly wrong for me. So my question is, whether there is a better alternative to convert arbitrary objects to byte[] to be able to compute hashes. Preferably a solution that works without using additional libraries or one using well established ones like Apache Commons.
(Beside that I am also open for other approaches to obtain SHA1/SHA512 hashes of arbitrary Java objects.)
Perhaps you can use UUIDs for your objects as immutable unique identifiers?
There are so many things wrong here...
You should have proper key classes with equals and hashCode implemented, instead of using random objects.
Serialization performance overhead can easily mean that such map will be slower than even trivial iteration search.
Default hashcode should not be used in most cases, as it might be different for objects which are 'equal' from business point of view. You should reimplement hashcode together with equals (which comes back to point 1). Whenever it has collisions due to pointer aliasing is irrelevant if it won't work poperly
Way overcomplicated method of closing in-memory streams. Just close them one after another, it is not external resource - if it fails, just let it fail, you don't need to close everything 100% in case of failures. You can also use one of closeable utilities (or try/catch with resources) to avoid some overhead
You don't need complicated digest of that byte array - use Arrays.hashCode, it WILL be good enough for your use cases (remember - don't do it anyway, point 1)
If you are still reading and still not willing to implement point 1, go back to point 1. And again. And again.
And to finally answer you question, use hessian serialization.
http://hessian.caucho.com/doc/hessian-overview.xtp
It is very similar to java one, just faster, shorter output and allows serializing objects which do not implement Serializable interface (at the risk of messing things up, you need to set special flag to allow that).
If you want to serialize a given object, i suggest you change your méthod like this :
public static byte[] convertToHashableByteArray(Serializable obj){
..........
..........
}
This question already has an answer here:
Java hashset how to serialise multiple objects
(1 answer)
Closed 6 years ago.
I'm using the code below, to get data from a file saved on my desktop to input into the game that I'm making.
try {
FileInputStream saves = new FileInputStream("/Users/Prodigy958/Desktop/Hack_exeSaves.ser");
ObjectInputStream in = new ObjectInputStream(saves);
test = (player) in.readObject();
in.close();
saves.close();
} catch(IOException error) {
error.printStackTrace();
return;
} catch(ClassNotFoundException error) {
error.printStackTrace();
return;
}
There is also the section which takes the player object and inputs it into a file.
player realPlayer = new player();
realPlayer.name = newName;
realPlayer.gender = newGender;
realPlayer.hasStarted = false;
try {
FileOutputStream fileOut = new FileOutputStream("/Users/Prodigy958/Desktop/Hack_exeSaves.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(realPlayer);
out.close();
fileOut.close();
} catch(IOException i) {
i.printStackTrace();
}
The issue that I am having is that if you save more than one player data onto the file, it calls up errors because it takes all the data and turns it into one player object. Do you know an easy way I would be able to split up the data? I have thought about using multiple files to store each different object's data. I have also though about taking out the data and splitting it up into separate objects, and then working from there, however I don't know where to start on the second one.
As others have already suggested, use a Serializable implementation of java.util.Collection. (Most of the java.util collections--such as java.util.ArrayList and java.util.HashSet--are Serializable.) A collection of 0 or 1 elements shouldn't bother you (it's not relevant to the serialization of the collection) unless your game has other business requirements that care, but... in that case, that's far beyond the scope of this question, and for you to handle on your own.
Motivation:
To aid in remote debugging (Java), it's useful to be able to request remote servers to send over arbitrary objects to my local machine for inspection. However, this means that the remote server must be able to serialize an arbitrary java object that is not known in advance at runtime.
In particular, I would like to be able to serialize even those objects which don't implement Serializable. I stumbled upon JBossSerialization which claimed with that with JBossSerialization...
...You can serialize classes that are not implementing Serializable
Great! And even better, I managed to find the code that supposedly demonstrates how to do this.
Problem
So pinching the code from schabell.org, I wrote a quick test to check that I could serialize and deserialize without problems:
import org.jboss.serial.io.JBossObjectInputStream;
import org.jboss.serial.io.JBossObjectOutputStream;
import java.io.*;
class MyObj { // Test class which doesn't implement Serializable
public int x;
MyObj(int x) {this.x = x;}
}
public class SerializationTest {
public static void main(String[] args) {
MyObj obj = new MyObj(1);
byte[] byteArray = getByteArrayFromObject(obj); // Try to serialize
MyObj result = (MyObj) getObjectFromByteArray(byteArray); // Try to deserialize
System.out.println(result.x);
}
// Code that I pinched from website below (http://www.schabell.org/2009/03/jboss-serialization-simple-example.html):
public static Object getObjectFromByteArray(byte[] bytes) {
Object result = null;
try {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new JBossObjectInputStream(bais);
result = ois.readObject(); // ERROR HERE!!!
ois.close();
} catch (IOException ioEx) {
ioEx.printStackTrace();
} catch (ClassNotFoundException cnfEx) {
cnfEx.printStackTrace();
}
return result;
}
public static byte[] getByteArrayFromObject(Object obj) {
byte[] result = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new JBossObjectOutputStream(baos);
oos.writeObject(obj);
oos.flush();
oos.close();
baos.close();
result = baos.toByteArray();
} catch (IOException ioEx) {
ioEx.printStackTrace();
}
return result;
}
}
Problem is that the test failed. Debugging indicated that I could only serialize, but not deserialize. The call to ois.readObject() on line 26 is the culprit and gives as SerializationException:
org.jboss.serial.exception.SerializationException: Could not create instance of MyObj - MyObj
at org.jboss.serial.classmetamodel.ClassMetaData.newInstance(ClassMetaData.java:342)
at org.jboss.serial.persister.RegularObjectPersister.readData(RegularObjectPersister.java:239)
at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.readObjectDescriptionFromStreaming(ObjectDescriptorFactory.java:412)
at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.objectFromDescription(ObjectDescriptorFactory.java:82)
at org.jboss.serial.objectmetamodel.DataContainer$DataContainerDirectInput.readObject(DataContainer.java:643)
at org.jboss.serial.io.JBossObjectInputStream.readObjectOverride(JBossObjectInputStream.java:163)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:364)
at SerializationTest.getObjectFromByteArray(SerializationTest.java:44)
at SerializationTest.main(SerializationTest.java:15)
Caused by: java.lang.InstantiationException: MyObj
at java.lang.Class.newInstance(Class.java:359)
at org.jboss.serial.classmetamodel.ClassMetaData.newInstance(ClassMetaData.java:334)
... 8 more
Does anyone know what's going wrong here and how I can get round this?
Or indeed if JBossSerialization isn't the right tool for this, what is?
Edit:
As #Dima points out, the SerializationException is caused by a lack of a public default constructor of the MyObj class. However, adding a default constructor to MyObj isn't an option as I'd like to be able to serialize arbitrary objects, including those without a default constructor.
Well, it is actually impossible to do what you want in a way, that would be both safe and universal.
You can take a look at Kryo, as someone suggested in comments as well. It does have a way to instantiate objects without invoking a constructor, but it is off by default and there is a good reason for it.
Consider this for example:
public class CanonicalObject {
public static HashMap<String,CannicalObject> canons = new HahMap<~>();
public String name;
private CanonicalObject(String name) {
this.name = name;
canons.put(name, this);
}
public static synchronized CanonicalObject getCanonicalInstance(String name) {
CanonicalObject co = canon.get(name);
return co == null ? new CanonicalObject(name) : co;
}
}
(This is a "semi-real-life" example, in that there are real uses for this pattern. I am aware of the "memory leak", there are ways to avoid it in real applications, but they are irrelevant to this example, so I am just ignoring that issue for the sake of simplicity).
If you serialize an instance of this object, when you deserialize it on the other end, the whole "canonicalization" part will be skipped, which can cause subtle problems in application, that are really hard to diagnose, such as comparisons like if(canon1 != canon2) fireMissile() resulting in "friendly fire" and, possibly, a WorldWar III.
Note, that the problem here is broader than just a constructor not invoked by deserialization: the canon.put call could very well be put into getCanonicalInstance() instead of the constructor, and that would present the problem even if the constructor was invoked.
This is an illustration of why, as a matter of policy, you should not be serializing objects that are not designed to be serialized. IT can sometimes work, but, when it does not, it results in situations that are really hard to detect, and usually even harder to fix.
I'm attempting to read a file that contains serialized objects of type Contact into an ArrayList contactsCollection. The issue I'm having is that the objects Contact never get added into the ArrayList.
try
{
ObjectInputStream in = new ObjectInputStream(new FileInputStream("contactList.dat"));
Contact temp;
while (in.available()!=0)
{
temp = (Contact)in.readObject();
contactsCollection.add(temp);
}
in.close();
}
This is a known behaviour of ObjectInputStream.available, it always returns 0, see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4954570. Instead, you can read objects from file until EOFException is thrown, catch it and break.
Actually, you entire approach is wrong: You should serialize the List, not each object.
All List implementations are Serializable. Just create the list, add your onjbects and serialize the list - the objects in it will be serialized too (if they implement Serializable, which obviuosly your do).
Then to deserialize, simply read in the object, and voila - you have a list with all our objects added in already.
ArrayLists are Serializable provided their contents are. If the code that stores the Contacts to the stream has them in an ArrayList, just read the list in all at once.
If not, you probably want to have the code storing the Contacts store the length first:
try (FileInputStream fis = new FileInputStream("contactList.dat"),
ObjectInputStream in = new ObjectInputStream(fis)) {
int size = in.readInt();
for (final int i = 0; i < size; ++i) {
contacts.add((Contact) in.readObject());
}
} catch (IOException e) {
// Handle exception
}
Mixing available and readObject is unwise; available would tell how many bytes are available without causing the stream to block, except that Evegniy's comment applies. Those bytes may not represent a complete object.
If you can't get the code writing to the stream to put the size in first, you'll simply have to loop through and depend on the fact that an EOFException is an IOException.
I'm working on a primitive RPG, and this class (supposedly) contains all the necessary data:
public class CPU implements Serializable{
private Map<String, Location> locations;
private Map<String, Location> places;
private Map<String, NPC> npcs;
private Game game;
private Player player;
private NPC currentNPC;
public CPU(){
}
(I didn't include the methods, but I think those are irrelevant right now...)
The class "Game" also contains the Player and the CPU as variables, but its constructor isn't the one to actually create them (those are created in the main() method, then added to the classes). This method is the one that's supposed to save the CPU class to a file, so that I can read all the data from it later:
public void SaveGame(String s){
String sav = s;
sav.concat(".dat");
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(sav));
oos.writeObject(cpu);
oos.close();
} catch(Exception ex) {
ex.printStackTrace();
}
}
And this is the method to load it from the file:
public void Load(String s){
if(s.contains(".dat")){
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(s));
cpu = (CPU)ois.readObject();
ois.close();
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
My question is basically: will this work? Am I able to simply serialize the CPU class and save it to a file, then read it back and be able to recover all the data from it (i.e the Player data)?
If I remember correctly, in Java "=" doesn't mean that the object on the right side will be copied, so my other problem is: when the method "Load" finishes, will the "cpu" (variable of the "Game"-class) still contain the CPU that I loaded from the file, and will I be able to read data from it?
Actually, it will work only if the original file name that you pass to the SaveGame() method contains ".dat".
Indeed, the reading method checks that condition, and the SaveGame() method (which should be named saveGame() to respect the Java naming conventions) doesn't append .dat to the file name as you think. Indeed, Strings are immutable, and the concat() method returns a new String, but doesn't modify the String it's called on. The code should be
String sav = s.concat(".dat");
You should also stop ignoring exceptions like you're doing, and you should always close the streams in a finally block. If you're under Java 7, use the try-with-resources construct.
If your program has permissions to write files, and all of the field classes (NPC, Game, Player. Location) are serializable as well, then it will work.
The cpu field of the Game class will contain the CPU loaded from the file, if no exception is thrown when reading the object.