本系列博客是在日常开发中遇到的各类异常、问题的分析总结。
今天在测试功能的时候,控制台抛出了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异常。
相关推荐
Java 中序列化 NotSerializableException 问题解决办法 Java 中序列化 NotSerializableException 问题是 Java 开发中常见的问题之一。 NotSerializableException 是 Java 中的一个异常,它发生在尝试序列化一个不...
在【描述】中提到的问题,当你尝试启用二级缓存时,如果实体类没有实现`Serializable`接口,MyBatis在尝试序列化对象存储到缓存时会抛出`java.io.NotSerializableException`。这是因为Java的序列化机制要求可序列化...
导入java.io.NotSerializableException; 导入java.io.ObjectStreamException; 导入java.io.Serializable; 导入java.security.AccessController; 导入java.security.AuthProvider; 导入java.security....
Struts2是一个强大的Java web应用程序框架,它基于MVC(Model-View-Controller)设计模式,为开发人员提供了构建高效、可维护性高的Web应用的工具。XWork是Struts2的核心组件,它负责处理Action的业务逻辑和控制流程...
3. `java.io.NotSerializableException`: 当尝试序列化一个未实现Serializable接口的对象时抛出的异常。 4. `sun.misc.BASE64Encoder`和`sun.misc.BASE64Decoder`(非标准API):用于将字节数组编码为Base64字符串,...
java.io.NotSerializableException: xxxxxx ``` 3. **解决方法** - **方法一**: 配置Tomcat不在关闭时保存Session数据。 在`server.xml`文件中的`<Context>`标签下添加以下内容: ```xml ...
在Java中,要实现对象的序列化,类必须实现`java.io.Serializable`接口。这个接口没有任何方法,仅仅作为一个标记,告诉Java虚拟机(JVM)这个类是可序列化的。 有两种主要的序列化方式: 1. 实现`Serializable`...
Java编程语言中,异常处理是程序健壮性的重要组成部分。当程序执行过程中遇到错误或特殊情况时,Java会抛出异常,这些异常分为两种主要类型:检查型异常(Checked Exceptions)和运行时异常(Runtime Exceptions)。...
### Java中将对象转换为byte数组的方法 在Java中,对象到byte数组的转换是一种常见的序列化技术,尤其是在网络通信、持久化存储等场景中。本文将详细介绍如何将一个Java对象转换为byte数组以及反向操作(即从byte...
可以使用`java.io.ObjectOutputStream`和`java.io.ObjectInputStream`来实现: ```java public class MyClass implements Serializable { private MyObject reference; // ...其他属性和方法... public MyClass...
9. **Java SE实用API**:涵盖java.util和java.text包中的类和接口,如日期和时间的处理、格式化、国际化等。 具体题目解析: - **QUESTION 1**:涉及对象的序列化。当一个实现序列化的类引用了未实现序列化的类时,...
在题目中,由于`Tree`类没有实现`Serializable`接口,所以在尝试序列化`Forest`实例时,会抛出`java.io.NotSerializableException`。 2. **对象的序列化与反序列化**:在问题2中,正确的序列化和反序列化代码是选项...
Java还提供了`java.io.ObjectStreamClass`和`java.io.ObjectStreamConstants`等辅助类来处理序列化相关的元数据,以及`java.io.NotSerializableException`和`java.io.OptionalDataException`等异常,它们分别在对象...
为了使一个Java对象能够被序列化,该类必须实现`java.io.Serializable`接口。虽然这个接口没有任何方法,但它的存在告诉JVM这个类的实例可以被转换为字节流。如果一个类没有实现这个接口,尝试序列化其对象时会抛出...
不实现该接口会导致NotSerializableException。 8. Word选中段落:在Word中,快速选中整个段落可以通过在段内任意位置连续点击鼠标三次。 9. 树的根结点数目:一棵树的根节点数量总是1。 10. 头结点的目的:在...
2. `Serializable`接口:在Java中,如果要序列化一个对象,该对象必须实现`Serializable`接口。否则,使用`ObjectInputStream`和`ObjectOutputStream`时会出现`NotSerializableException`异常。 3. Internet在中国...
如果不实现此接口,尝试序列化时会抛出`NotSerializableException`异常。 2. **DOM**:DOM(Document Object Model)是一种用于表示XML和HTML文档的标准模型,它允许程序和脚本动态更新、添加、删除和改变元素和...
12. **对象序列化**:在Java中,使用`ObjectInputStream`和`ObjectOutputStream`进行对象持久化时,对象必须实现`Serializable`接口,否则会抛出`NotSerializableException`异常。 13. **计算机字长**:字长为4个...
- **对象序列化**:在IO操作中,可以使用`ObjectOutputStream`和`ObjectInputStream`进行对象的序列化和反序列化。`defaultReadObject()`和`defaultWriteObject()`方法用于处理对象的默认字段值。 8. **Java 集合...
5. 序列化与对象持久化:Java中,如果要使用ObjectInputStream和ObjectOutputStream来持久化对象,该对象必须实现Serializable接口,否则会抛出NotSerializableException异常。 6. 异常处理:在Java中,try-catch块...