1

My Goal: I need to keep the App state exactly in same sate after shutdown, lets say it's equivalent to "suspend" state.

My Problem : I do know that serialization mechanism doesn't save transient variables neither static variables. However I need to maintain the static variables in exactly same state after App suspension/shut down.

Approach-1 : I could save the state of static variable(s) into a different file, using my "file format", and serialize the objects into a different one.

a) Is this the "normal" approach?

Approach-2 : If I extend the ObjectInputStream/ObjectOutputStreamand override the methods readStreamHeader/writeStreamHeaderI can write whatever I want. So I can also write my static variables.

b) Am I doing something I should not?

Here's the code I've written testing approach-2, and seams to work fine. Please note, I'm not a Java programmer, so for it's very important to understand best practices, if there's any in this particular case.

@SuppressWarnings("serial")
class SequenceIdentifier implements Serializable
{
    protected static long seqIdentifier_ = 1L;  //This variable MUST NOT be reseted.
    private long id_; //Object variable to be serialised.

    private SequenceIdentifier(long id)     
    {   id_ = id;
    }
    @Override
    public String toString()
    {   return ("Id : " + id_ + " of " + seqIdentifier_);
    }
    public static SequenceIdentifier newInstance()
    {   return new SequenceIdentifier(seqIdentifier_++);
    }   
}

final class OOStream extends ObjectOutputStream 
{
    public OOStream(OutputStream out) throws IOException
    {   super(out);
    }   
    @Override
    protected void writeStreamHeader() throws IOException
    {   super.writeLong(SequenceIdentifier.seqIdentifier_);
    }
}

final class OIStream extends ObjectInputStream 
{
    public OIStream(InputStream in) throws IOException
    {   super(in);
    }
    @Override
    protected void readStreamHeader() throws IOException 
    {   SequenceIdentifier.seqIdentifier_ = super.readLong();
    }
}

public class Main
{
    public static void dump(ArrayList<SequenceIdentifier> ids)
    {
        for (SequenceIdentifier id : ids)
            System.out.println(id);
    }

    public static void saveData()
    {
        ArrayList<SequenceIdentifier> ids = new ArrayList<>(Arrays.asList(SequenceIdentifier.newInstance(),
                                                                                            SequenceIdentifier.newInstance(),
                                                                                            SequenceIdentifier.newInstance(),
                                                                                            SequenceIdentifier.newInstance()));
        try (OOStream oOut = new OOStream(new FileOutputStream("foo.bin")))
        {   oOut.writeObject(ids);
        } catch (Exception e)
        {   System.err.println(e);
        }       
        dump(ids);
    }

    @SuppressWarnings("unchecked")
    public static void loadData()
    {
        ArrayList<SequenceIdentifier> ids = null;
        try (OIStream oIn = new OIStream(new FileInputStream("foo.bin")))
        {   ids = (ArrayList<SequenceIdentifier>)oIn.readObject(); 
        } catch (Exception e)
        {   System.err.println(e);
        }       
        dump(ids);
    }

    public static void main(String[] args)
    {
        saveData();
        System.out.println("Counter at this point " + SequenceIdentifier.seqIdentifier_);

        SequenceIdentifier.seqIdentifier_ = 0;
        loadData();
        System.out.println("Counter at this point " + SequenceIdentifier.seqIdentifier_);
    }
}

2 Answers 2

2

I would create a separate Memento-class containing all the relevant data as fields and de-/serialize that.

class MyClassWithStaticFields1 {
    private static String field;
}
class MyClassWithStaticFields2 {
    private static String field;
}

class StaticMemento {
    String field1;
    String field2;
}

// serialization
StaticMemento mem = new StaticMemento();
mem.field1 = MyClassWithStaticFields1.field;
mem.field2 = MyClassWithStaticFields2.field;
outputStream.writeObject(mem);

// deserialize
StaticMemento mem = outputStream.readObject();
MyClassWithStaticFields1.setField(mem.field1);
MyClassWithStaticFields2.setField(mem.field2);

So basically your Approach-1.

Sign up to request clarification or add additional context in comments.

Comments

0

Several possibilities.

  1. Make it non-static.
  2. Write complementary readObect()/writeObject() methods that call defaultReadObject() and defaultWriteObject() respectively and then serialize/deserialize the field.
  3. Write complementary writeReplace()/readResolve() methods that substitute a proxy object that does contain this member as a non-transient non-static member.
  4. Make the object Externalizable and take complete control of the serialization process yourself in the associated methods.
  5. Review your requirement.

2 Comments

I've just now started my java "adventure" so could you example me what do you mean in solution 2 and 3?
Have a look at the Java Object Serialization Specification and the Serialization chapter of the Java Tutorial.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.