`
ywu
  • 浏览: 456467 次
  • 性别: Icon_minigender_1
  • 来自: 无锡
社区版块
存档分类
最新评论

java.io.NotSerializableException: java.util.RandomAccessSubList

阅读更多

本系列博客是在日常开发中遇到的各类异常、问题的分析总结。

 

今天在测试功能的时候,控制台抛出了java.io.NotSerializableException: java.util.RandomAccessSubList异常,具体的堆栈信息如下:
java.io.NotSerializableException: java.util.RandomAccessSubList
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at com.ibm.commerce.multichannel.dao.TaskDao.objectToBytes(TaskDao.java:301)
at com.ibm.commerce.multichannel.dao.TaskDao.createBatchTask(TaskDao.java:147)
at com.ibm.commerce.multichannel.flow.task.inventory.BatchUpdateInventoryTask.doTask(BatchUpdateInventoryTask.java:98)
at com.ibm.commerce.multichannel.flow.task.Task.run(Task.java:89)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

简要介绍下代码中的场景:
在TaskDao.java:301行,在将java应用中的对象保存到数据库中时,使用了ObjectOutputStream将对象转换为字节数组,然后保存到数据库中:
ByteArrayOutputStream baos = null;
ObjectOutputStream oos = null;
try {
    baos = new ByteArrayOutputStream();
    oos = new ObjectOutputStream(baos);
    oos.writeObject(obj);
    return baos.toByteArray();
} catch (Exception e) {
    ...
}

我们再来看下调用TaskDao的地方的代码:
InventoryList inventoryList = (InventoryList)this.getData();
List<SKUInventory> skus = inventoryList.getList();
List<Task> tasks=new ArrayList<Task>();
...
if(skus.size()>0 && (this.getChannelId() == CHANNEL_ID_YHD)){
    int totalBatch = ((skus.size() % BATCH_SIZE) == 0 ? (skus.size() / BATCH_SIZE) : (skus.size() / BATCH_SIZE + 1));
    ...
    if(i == (totalBatch-1)){
        batchInventoryTask.setData(skus.subList(BATCH_SIZE * i, skus.size()));
    }else{
        batchInventoryTask.setData(skus.subList(BATCH_SIZE * i, BATCH_SIZE * (i + 1)));
    }
    ...
    tasks.add(batchInventoryTask);
}
taskDao.createBatchTask(tasks);

这里省略了不相干的代码,batchInventoryTask.setData中的参数就是TaskDao中要转成字节数组的Object,可以看出,这个Object其实是List的subList方法返回的结果,这边List<SKUInventory> skus的真实类型是ArrayList。

我们来分析下异常:
java.io.NotSerializableException: java.util.RandomAccessSubList,凭经验猜测,可能是序列化相关问题,看下ObjectOutputStream的介绍,JDK1.6 API帮助文档.CHM中对其的解释是这样的(片段):
...
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。
只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。

即能被ObjectOutputStream 操作的对象必须实现了 java.io.Serializable接口,很有可能代码中转换的Object没有实现 java.io.Serializable接口,而这个Object的实际类型是List的subList方法返回的结果。

再来分析下List的subList方法。subList方法签名如下:
List<E> subList(int fromIndex, int toIndex);
应用中List的实现使用的是ArrayList,我们看下ArrayList中subList方法的实现;
ArrayList中并没有subList方法的实现,看下ArrayList的定义
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
其继承了AbstractList,以下代码是AbstractList中subList方法的实现:
public List<E> subList(int fromIndex, int toIndex) {
    return (this instanceof RandomAccess ?
            new RandomAccessSubList<E>(this, fromIndex, toIndex) :
            new SubList<E>(this, fromIndex, toIndex));
}
从ArrayList的定义中看到,其实现了RandomAccess接口,因此this instanceof RandomAccess 返回true,subList方法返回的是new RandomAccessSubList<E>(this, fromIndex, toIndex)

再来看下RandomAccessSubList的定义:
class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
    ...
}
其继承了SubList,实现了RandomAccess 接口,以下是他的继承结构


而RandomAccess 是一个空接口,其定义如下
public interface RandomAccess {
}

再来看下SubList定义:
class SubList<E> extends AbstractList<E> {
}
其继承了AbstractList

AbstractList定义如下:
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
}

List接口定义如下:
public interface List<E> extends Collection<E> {
}

AbstractCollection定义如下:
public abstract class AbstractCollection<E> implements Collection<E> {
}

最终汇聚到Collection接口,Collection接口定义如下:
public interface Collection<E> extends Iterable<E> {
}

再来看下Iterable定义:
public interface Iterable<T> {
}

废了这么多劲看了这么多接口、实现类定义,只想说明一件事,就是RandomAccessSubList没有实现java.io.Serializable接口,因此在TaskDao中将其转换为字节数组时才会抛出java.io.NotSerializableException: java.util.RandomAccessSubList异常。

  • 大小: 6.9 KB
分享到:
评论

相关推荐

    java 中序列化NotSerializableException问题解决办法

    Java 中序列化 NotSerializableException 问题解决办法 Java 中序列化 NotSerializableException 问题是 Java 开发中常见的问题之一。 NotSerializableException 是 Java 中的一个异常,它发生在尝试序列化一个不...

    7.7初始mybatis个人笔记.docx

    在【描述】中提到的问题,当你尝试启用二级缓存时,如果实体类没有实现`Serializable`接口,MyBatis在尝试序列化对象存储到缓存时会抛出`java.io.NotSerializableException`。这是因为Java的序列化机制要求可序列化...

    aesjava源码-THIS-.-IS-GREAT-:////IntelliJIDEA从.class文件重新创建的源代码//(由Fernflo

    导入java.io.NotSerializableException; 导入java.io.ObjectStreamException; 导入java.io.Serializable; 导入java.security.AccessController; 导入java.security.AuthProvider; 导入java.security....

    struts2 依赖核心包 --xwork 源文件

    Struts2是一个强大的Java web应用程序框架,它基于MVC(Model-View-Controller)设计模式,为开发人员提供了构建高效、可维护性高的Web应用的工具。XWork是Struts2的核心组件,它负责处理Action的业务逻辑和控制流程...

    java自动序列化

    3. `java.io.NotSerializableException`: 当尝试序列化一个未实现Serializable接口的对象时抛出的异常。 4. `sun.misc.BASE64Encoder`和`sun.misc.BASE64Decoder`(非标准API):用于将字节数组编码为Base64字符串,...

    java session

    java.io.NotSerializableException: xxxxxx ``` 3. **解决方法** - **方法一**: 配置Tomcat不在关闭时保存Session数据。 在`server.xml`文件中的`&lt;Context&gt;`标签下添加以下内容: ```xml ...

    java中的序列号和反序列化.doc

    在Java中,要实现对象的序列化,类必须实现`java.io.Serializable`接口。这个接口没有任何方法,仅仅作为一个标记,告诉Java虚拟机(JVM)这个类是可序列化的。 有两种主要的序列化方式: 1. 实现`Serializable`...

    JAVA常见异常...........

    Java编程语言中,异常处理是程序健壮性的重要组成部分。当程序执行过程中遇到错误或特殊情况时,Java会抛出异常,这些异常分为两种主要类型:检查型异常(Checked Exceptions)和运行时异常(Runtime Exceptions)。...

    java中把对象转化为byte数组的方法.doc

    ### Java中将对象转换为byte数组的方法 在Java中,对象到byte数组的转换是一种常见的序列化技术,尤其是在网络通信、持久化存储等场景中。本文将详细介绍如何将一个Java对象转换为byte数组以及反向操作(即从byte...

    Java对象的深克隆与浅克隆详解.zip(wcb2003)

    可以使用`java.io.ObjectOutputStream`和`java.io.ObjectInputStream`来实现: ```java public class MyClass implements Serializable { private MyObject reference; // ...其他属性和方法... public MyClass...

    2010年SCJP标准题库

    9. **Java SE实用API**:涵盖java.util和java.text包中的类和接口,如日期和时间的处理、格式化、国际化等。 具体题目解析: - **QUESTION 1**:涉及对象的序列化。当一个实现序列化的类引用了未实现序列化的类时,...

    OCJP题库JAVA考试

    在题目中,由于`Tree`类没有实现`Serializable`接口,所以在尝试序列化`Forest`实例时,会抛出`java.io.NotSerializableException`。 2. **对象的序列化与反序列化**:在问题2中,正确的序列化和反序列化代码是选项...

    Serialization:Java中的序列化

    Java还提供了`java.io.ObjectStreamClass`和`java.io.ObjectStreamConstants`等辅助类来处理序列化相关的元数据,以及`java.io.NotSerializableException`和`java.io.OptionalDataException`等异常,它们分别在对象...

    关于Java对象序列化您不知道的5件事Java开发Java

    为了使一个Java对象能够被序列化,该类必须实现`java.io.Serializable`接口。虽然这个接口没有任何方法,但它的存在告诉JVM这个类的实例可以被转换为字节流。如果一个类没有实现这个接口,尝试序列化其对象时会抛出...

    2021-2022计算机二级等级考试试题及答案No.18807.docx

    不实现该接口会导致NotSerializableException。 8. Word选中段落:在Word中,快速选中整个段落可以通过在段内任意位置连续点击鼠标三次。 9. 树的根结点数目:一棵树的根节点数量总是1。 10. 头结点的目的:在...

    2021-2022计算机二级等级考试试题及答案No.9392.docx

    2. `Serializable`接口:在Java中,如果要序列化一个对象,该对象必须实现`Serializable`接口。否则,使用`ObjectInputStream`和`ObjectOutputStream`时会出现`NotSerializableException`异常。 3. Internet在中国...

    2021-2022计算机二级等级考试试题及答案No.3179.docx

    如果不实现此接口,尝试序列化时会抛出`NotSerializableException`异常。 2. **DOM**:DOM(Document Object Model)是一种用于表示XML和HTML文档的标准模型,它允许程序和脚本动态更新、添加、删除和改变元素和...

    2021-2022计算机二级等级考试试题及答案No.18292.docx

    12. **对象序列化**:在Java中,使用`ObjectInputStream`和`ObjectOutputStream`进行对象持久化时,对象必须实现`Serializable`接口,否则会抛出`NotSerializableException`异常。 13. **计算机字长**:字长为4个...

    SCJP认证考试题库1.pdf

    - **对象序列化**:在IO操作中,可以使用`ObjectOutputStream`和`ObjectInputStream`进行对象的序列化和反序列化。`defaultReadObject()`和`defaultWriteObject()`方法用于处理对象的默认字段值。 8. **Java 集合...

    2021-2022计算机二级等级考试试题及答案No.5129.docx

    5. 序列化与对象持久化:Java中,如果要使用ObjectInputStream和ObjectOutputStream来持久化对象,该对象必须实现Serializable接口,否则会抛出NotSerializableException异常。 6. 异常处理:在Java中,try-catch块...

Global site tag (gtag.js) - Google Analytics