Serialization in Java, invalid type code 00
Asked Answered
F

4

7

I'm getting an error (java.io.StreamCorruptedException: invalid type code: 00) when reading in a serialised object. Here is the class that implements serializable:

package guts;

import cc.mallet.classify.*;
import java.io.*;


public class NaiveBayesWithID implements Serializable  {

private NaiveBayes nb;
private static final long serialVersionUID = 1;
    private static final int CURRENT_SERIAL_VERSION = 1;

public NaiveBayesWithID(NaiveBayes nb) {
this.nb = nb;
}
public NaiveBayesWithID(){
this.nb = null;
}

    public void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    int version = in.readInt();
    if (version != CURRENT_SERIAL_VERSION)
        throw new ClassNotFoundException("Mismatched NaiveBayesTrainer versions: wanted " +
                CURRENT_SERIAL_VERSION + ", got " +
                version);

    //default selections for the kind of Estimator used

    NaiveBayesWithID test = (NaiveBayesWithID) in.readObject();
   // nb = test.returnNB();
    }

    public void writeObject(ObjectOutputStream out) throws IOException
    {
    out.writeInt(CURRENT_SERIAL_VERSION);

    //default selections for the kind of Estimator used
    out.writeObject(this);
    }

    public NaiveBayes returnNB(){
    return nb;
    }

    public void setNB(NaiveBayes nb){
        this.nb = nb;
    }

}

and here is the stack trace:

java.io.StreamCorruptedException: invalid type code: 00
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1355)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at java.util.ArrayList.readObject(ArrayList.java:593)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1848)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at cc.mallet.pipe.SerialPipes.readObject(SerialPipes.java:142)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1848)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at guts.NaiveBayesWithID.readObject(NaiveBayesWithID.java:29)
at controllers.Application.predict(Application.java:481)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:408)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:403)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:176)
at play.server.PlayHandler$NettyInvocation.execute(PlayHandler.java:169)
at play.Invoker$Invocation.run(Invoker.java:187)
at play.server.PlayHandler$NettyInvocation.run(PlayHandler.java:149)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:206)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)

Does anyone know how I can get more information on the error? Or which object java is expecting?

Fauman answered 9/2, 2012 at 18:57 Comment(2)
Duplicate #2234906Yell
That does not fix the problem. Can you provide an explanation as to why it should?Fauman
C
5

You have implemented a recursive writeObject method: when you write an instance to an output stream, it calls the writeObject method, which writes an int, and then writes the object to the output stream, which write an int, etc.

The goal of the serialVersionUID field is to check that the objects are compatible. It's done natively by the serialization mechanism. You don't have to do anything except changing the serialVersionUID value when the class changes.

Colleague answered 9/2, 2012 at 19:4 Comment(6)
I've changed the method of read and write so that it now does not write or read the CURRENT_SERIAL_VERSION and I'm getting exactly the same errorFauman
It's not this field that cause a problem. It's this. Don't implement any writeObject or readObject method. The serialization mechanism will write your object without any problem without these methods.Colleague
I've just tried taking those methods out and reading and writing the object directly from the object output stream, the same method occurs. Are there any other reasons why it could be caused?Fauman
Try serializing the inner object, and see if it causes the same problem. Repeat until you find the culprit. And check if it's not a problem with the way you write and read. Try serializing to a ByteArrayouOutputStream and reading from a ByteArrayInputStream.Colleague
You don't have to change the serialVersionUID when the class changes. Hasn't anybody read the Versioning chapter of the Object Serialization Specification?Lipography
@EJP: I have. It says: "Each versioned class must identify the original class version for which it is capable of writing streams and from which it can read." (emphasis mine). So yes, if you make changes to the class that make its serialization format incompatible with the previous version of the class, you're supposed to change the serialVersionUID. BTW, the default value, computed by the VM, changes as soon as you add, remove or reorder fields, precisely to signal that a previous or future class which wouldn't have the same fields in the same order would be incompatible.Colleague
M
1

If the JVM cannot find the class when you attempt to read a serialized object, this exception will be generated. Check that updated jar/class files are available in the class path etc..

If you're running mallet from the command line, it may be looking at the unzipped mallet jars and class files from a downloaded distribution, and not at your nice new class files created in your downloaded source repository..

Don't feel too bad - I've seen this happen to others, and have done it myself (though I got a more informative "ClassNotFoundException" to help me figure it out :)

Martyrdom answered 7/11, 2012 at 4:7 Comment(0)
T
0

Came here to find solution for Mallet classifier deserialization. Finally my problem was that I trained and serialized the model in one Eclipse project and tried to deserialize in another Eclipse project. One of the classes (among those I created) in the serialized object was only on the class path of the former project and not on the class path of the latter.

Triliteral answered 14/5, 2016 at 0:28 Comment(2)
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From ReviewAegaeon
So you mean the original question was "Does anyone know how I can get more information on the error? Or which object java is expecting?" so the answer should be about how to get more information on the error? Or the real goal of the asker is to solve the problem? My answer gives a solution to the real problem. Sorry for that.Triliteral
M
-2

Run to get the answer:

package so.java9217010;
import java.io.*;

public class SerializeMe implements Serializable{


    private String foo;
    private static final long serialVersionUID = 1;
    private static final int CURRENT_SERIAL_VERSION = 1;

    public SerializeMe(String foo) {
        this.foo = foo;
    }
    public SerializeMe(){
    }

    public SerializeMe readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        int version = in.readInt();
        if (version != CURRENT_SERIAL_VERSION)
            throw new ClassNotFoundException("Mismatched NaiveBayesTrainer versions: wanted " +
                    CURRENT_SERIAL_VERSION + ", got " +
                    version);

        //default selections for the kind of Estimator used

        return (SerializeMe) in.readObject();
        // nb = test.returnNB();
    }

    public void writeObject(ObjectOutputStream out) throws IOException
    {
        out.writeInt(CURRENT_SERIAL_VERSION);

        //default selections for the kind of Estimator used
        out.writeObject(this);
    }

    public String returnNB(){
        return foo;
    }

    public void setNB(String foo){
        this.foo = foo;
    }
    public static void main(String[] args) throws Exception {
        SerializeMe o = new SerializeMe("hello");
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream oout = new ObjectOutputStream(bout);

        o.writeObject(oout);
        oout.flush();
        byte[] buff = bout.toByteArray();

        ByteArrayInputStream bin = new ByteArrayInputStream(buff);
        ObjectInputStream oin = new ObjectInputStream(bin);
        SerializeMe ro = o.readObject(oin);
        System.out.format(
                "got: %s -- the problem is most likely in the library you are using ...\n",
                      ro.returnNB());
    }
}
Messapian answered 9/2, 2012 at 19:44 Comment(1)
This is not an answer. Consider someone reading from a smartphone that can't run the code; then this answer won't help them.Immiscible

© 2022 - 2024 — McMap. All rights reserved.