非可序列化对象异常

时间:2012-10-06 17:51:02

标签: java serialization memcached

我正在尝试在Memcached客户端中设置对象列表(可序列化)。我正在使用set方法。我收到此错误消息:

  

目标VM发生异常:非序列化对象

所以它不允许我在MemcachedClient对象中设置值。这是我的代码:

MemcachedClient client = CacheConnectionUtil.connectToCacheServer(this.applicationEnv);
client.set(generateCacheKey(namespace, key), expireInSeconds, value);
// value is a list of objects that implements serializable

为什么我收到此错误消息?

4 个答案:

答案 0 :(得分:3)

可能无法序列化MemcachedClient类中的对象。您有2个选项可以解决问题:

  1. 确保那里的所有类都实现Serializable接口。

    public class MemcachedClient {
    
        //AnotherClass must implement Serializable too.
        private AnotherClass anotherClassInstance;
    }
    
  2. 如果其他类未实现Serializable(并且您无法修改这些类以使其Serializable),则添加transient关键字以便这些对象不会被序列化

    public class MemcachedClient {
    
        //AnotherClass doesn't implement Serializable.
        private transient AnotherClass anotherClassInstance;
    }
    
  3. 如果在反序列化AnotherClass对象时必须有MemcachedClient的实例,那么可以根据需要编写readObject(ObjectInputStream is)来创建实例:

    public class MemcachedClient {
    
        //AnotherClass doesn't implement Serializable.
        private transient AnotherClass anotherClassInstance;
    
        private void writeObject(ObjectOutputStream os) throws IOException, ClassNotFoundException {
            os.defaultWriteObject();
        }
    
        private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException {
            is.defaultReadObject();
            anotherClassInstance = new AnotherClass();
            //more logic to get a consistant AnotherClass instance.
        }
    }
    

    根据Brian的评论,假设这个MemcachedClient类来自第三方库并且您无法对其进行修改,那么您将有一个如第2点所述的场景:

    public class MyClass {
    
        //MemcachedClient can't be modified and doesn't implement Serializable interface
        //the only solution would be using the transient modifier
        private transient MemcachedClient memcachedClient;
    
        //MyClass attributes and methods...
    
        //If you need to keep a MemcachedClient instance when deserializing the object
        //just write the readObject method
    
        private void writeObject(ObjectOutputStream os) throws IOException, ClassNotFoundException {
            os.defaultWriteObject();
        }
    
        private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException {
            is.defaultReadObject();
            memcachedClient= new MemcachedClient();
            //more logic to get a consistant MemcachedClient instance.
        }
    }
    

答案 1 :(得分:3)

来自Serializable javadocs:

  

遍历图形时,可能会遇到不支持Serializable接口的对象。在这种情况下,将抛出NotSerializableException并将标识非可序列化对象的类。

Memcached似乎隐藏了异常消息的其余部分,因此您必须自己识别不可序列化的对象。

你说values是你自己对象的列表。我的猜测是你的对象包含的东西不是Serializable,或者它包含包含其他的东西,而不是Serializable。浏览列表中对象的类,确保其下的每个对象都实现Serializable

例如,如果A实施Serializable

public class A implements Serializable {
    private B b;
    // ...
}

并且B没有:

public class B { ... }

然后,使用A(可能是Memcached库中的默认序列化程序正在执行的操作)序列化ObjectOutputStream的任何尝试都将抛出NotSerializableException因为其字段{{1} ,是一种非可序列化的类型,这就是你得到的。

答案 2 :(得分:1)

确保您的对象实现Serializable(甚至是从对象引用的所有对象)

答案 3 :(得分:0)

我在序列化列表时遇到了类似的问题。我的问题原来是我正在使用List.subList,即使List只包含可序列化的项,subList返回的List也不可序列化。一个快速的解决方案是做类似

的事情
List mySublist = new ArrayList().addAll(originalList.subList(...));