java序列化ClassNotFoundException
简单的想从保存的对象中重新解析出对象,用了逆序列化,可是报错:
java.lang.ClassNotFoundException: xxxxxxxxxxxx
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:622)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1593)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at xxxxxxxxxxxxxxxxx(TestMetadata.java:103)
提示类找不到,但实际上类文件是确确实实存在的,那就上网搜,果然找到答案。
可以参考文章: http://www.javapractices.com/topic/TopicAction.do?Id=45
最基本的两点:
1) 需要同样的包名
2) 同样的序列化ID
文章: http://www.javapractices.com/topic/TopicAction.do?Id=45如下:
Do not implement Serializable lightly, since it restricts future flexibility, and publicly exposes class implementation details which are usually private. As well, implementing Serializable correctly is not trivial.
The serialVersionUID is a universal version identifier for a Serializable class. Deserialization uses this number to ensure that a loaded class corresponds exactly to a serialized object. If no match is found, then anInvalidClassException is thrown.
Guidelines for serialVersionUID:
- always include it as a field, for example:
private static final long serialVersionUID = 7526472295622776147L;
- include this field even in the first version of the class, as a reminder of its importance
- don't change the value of this field in future versions, unless you are knowingly making changes to the class which will render it incompatible with old serialized objects
- new versions of Serializable classes may or may not be able to read old serialized objects; it depends upon the nature of the change; provide a pointer to Oracle's guidelines for what constitutes a compatible change, as a convenience to future maintainers
Modern IDE's can generate a value of serialVersionUID for you. In addition, the JDK includes the serialver tool for generating these values. Here are the docs for both Win and Unix. (The class name you pass to this tool doesn't include the .class extension.)
readObject and writeObject:
- readObject implementations always start by calling default methods
- deserialization must be treated as any constructor: validate the object state at the end of deserializing - this implies that readObject should almost always be implemented in Serializable classes, such that this validation is performed.
- deserialization must be treated as any constructor: if constructors make defensive copies for mutable object fields, so must readObject
- when serializing a Collection, store the number of objects in the Collection as well, and use this number to read them back in upon deserialization; avoid tricks using null
Other points:
- use javadoc's @serial tag to denote Serializable fields
- the .ser extension is conventionally used for files representing serialized objects
- no static or transient fields undergo default serialization
- extendable classes should not be Serializable, unless necessary
- inner classes should rarely, if ever, implement Serializable
- container classes should usually follow the style of Hashtable, which implements Serializable by storing keys and values, as opposed to a large hash table data structure
Example
import java.io.Serializable;
import java.text.StringCharacterIterator;
import java.util.*;
import java.io.*; public final class SavingsAccount implements Serializable { /**
* This constructor requires all fields to be passed as parameters.
*
* @param aFirstName contains only letters, spaces, and apostrophes.
* @param aLastName contains only letters, spaces, and apostrophes.
* @param aAccountNumber is non-negative.
* @param aDateOpened has a non-negative number of milliseconds.
*/
public SavingsAccount(
String aFirstName, String aLastName, int aAccountNumber, Date aDateOpened
){
setFirstName(aFirstName);
setLastName(aLastName);
setAccountNumber(aAccountNumber);
//make a defensive copy of the mutable Date passed to the constructor
setDateOpened(new Date(aDateOpened.getTime()));
//there is no need here to call validateState.
} public SavingsAccount(){
this("FirstName", "LastName", 0, new Date(System.currentTimeMillis()));
} public String getFirstName(){
return fFirstName;
} public String getLastName(){
return fLastName;
} public int getAccountNumber(){
return fAccountNumber;
} /**
* Returns a defensive copy of the field.
* The caller may change the state of the returned object in any way,
* without affecting the internals of this class.
*/
public Date getDateOpened() {
return new Date(fDateOpened.getTime());
} /**
* Names must contain only letters, spaces, and apostrophes.
* Validate before setting field to new value.
*
* @throws IllegalArgumentException if the new value is not acceptable.
*/
public void setFirstName(String aNewFirstName) {
validateName(aNewFirstName);
fFirstName = aNewFirstName;
} /**
* Names must contain only letters, spaces, and apostrophes.
* Validate before setting field to new value.
*
* @throws IllegalArgumentException if the new value is not acceptable.
*/
public void setLastName (String aNewLastName) {
validateName(aNewLastName);
fLastName = aNewLastName;
} /**
* Validate before setting field to new value.
*
* @throws IllegalArgumentException if the new value is not acceptable.
*/
public void setAccountNumber(int aNewAccountNumber){
validateAccountNumber(aNewAccountNumber);
fAccountNumber = aNewAccountNumber;
} public void setDateOpened(Date aNewDate){
//make a defensive copy of the mutable date object
Date newDate = new Date(aNewDate.getTime());
validateDateOpened(newDate);
fDateOpened = newDate;
} // PRIVATE /**
* The client's first name.
* @serial
*/
private String fFirstName; /**
* The client's last name.
* @serial
*/
private String fLastName; /**
* The client's account number.
* @serial
*/
private int fAccountNumber; /**
* The date the account was opened.
* @serial
*/
private Date fDateOpened; /**
* Determines if a de-serialized file is compatible with this class.
*
* Maintainers must change this value if and only if the new version
* of this class is not compatible with old versions. See Sun docs
* for <a href=http://java.sun.com/products/jdk/1.1/docs/guide
* /serialization/spec/version.doc.html> details. </a>
*
* Not necessary to include in first version of the class, but
* included here as a reminder of its importance.
*/
private static final long serialVersionUID = 7526471155622776147L; /**
* Verify that all fields of this object take permissible values; that is,
* this method defines the class invariant.
*
* In this style of implementation, both the entire state of the object
* and its individual fields can be validated without repeating or
* duplicating code.
* Each condition is defined in one place. Checks on the entire
* object are performed at the end of object construction, and at
* the end of de-serialization. Checks on individual fields are
* performed at the start of the corresponding setXXX method.
* As well, this style replaces the if's and throwing
* of exceptions at the start of a setXXX, with a simple call to validateXXX.
* Validation is separated from the regular path of execution,
* which leads to improved legibility.
*
* @throws IllegalArgumentException if any field takes an unpermitted value.
*/
private void validateState() {
validateAccountNumber(fAccountNumber);
validateName(fFirstName);
validateName(fLastName);
validateDateOpened(fDateOpened);
} /**
* Ensure names contain only letters, spaces, and apostrophes.
*
* @throws IllegalArgumentException if field takes an unpermitted value.
*/
private void validateName(String aName){
boolean nameHasContent = (aName != null) && (!aName.equals(""));
if (!nameHasContent){
throw new IllegalArgumentException("Names must be non-null and non-empty.");
}
StringCharacterIterator iterator = new StringCharacterIterator(aName);
char character = iterator.current();
while (character != StringCharacterIterator.DONE){
boolean isValidChar =
(Character.isLetter(character) ||
Character.isSpaceChar(character) ||
character =='\''
);
if (isValidChar) {
//do nothing
}
else {
String message = "Names can contain only letters, spaces, and apostrophes.";
throw new IllegalArgumentException(message);
}
character = iterator.next();
}
} /**
* AccountNumber must be non-negative.
* @throws IllegalArgumentException if field takes an unpermitted value.
*/
private void validateAccountNumber(int aAccountNumber){
if (aAccountNumber < 0) {
String message = "Account Number must be greater than or equal to 0.";
throw new IllegalArgumentException(message);
}
} /**
* DateOpened must be after 1970.
* @throws IllegalArgumentException if field takes an unpermitted value.
*/
private void validateDateOpened(Date aDateOpened) {
if(aDateOpened.getTime() < 0) {
throw new IllegalArgumentException("Date Opened must be after 1970.");
}
} /**
* Always treat de-serialization as a full-blown constructor, by
* validating the final state of the de-serialized object.
*/
private void readObject(
ObjectInputStream aInputStream
) throws ClassNotFoundException, IOException {
//always perform the default de-serialization first
aInputStream.defaultReadObject(); //make defensive copy of the mutable Date field
fDateOpened = new Date(fDateOpened.getTime()); //ensure that object state has not been corrupted or tampered with maliciously
validateState();
} /**
* This is the default implementation of writeObject.
* Customise if necessary.
*/
private void writeObject(
ObjectOutputStream aOutputStream
) throws IOException {
//perform the default serialization for all non-transient, non-static fields
aOutputStream.defaultWriteObject();
}
}
java序列化ClassNotFoundException的更多相关文章
- 对象逆序列化报错:java.lang.ClassNotFoundException
简单的想从保存的对象中又一次解析出对象.用了逆序列化,但是报错: java.lang.ClassNotFoundException: xxxxxxxxxxxx at java.net.URLClass ...
- Java 序列化与反序列化
1.什么是序列化?为什么要序列化? Java 序列化就是指将对象转换为字节序列的过程,而反序列化则是只将字节序列转换成目标对象的过程. 我们都知道,在进行浏览器访问的时候,我们看到的文本.图片.音频. ...
- Java序列化与反序列化
Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列 ...
- Android使用HttpURLConnection通过POST方式发送java序列化对象
使用HttpURLConnection类不仅可以向WebService发送字符串,还可以发送序列化的java对象,实现Android手机和服务器之间的数据交互. Android端代码: public ...
- Java 序列化Serializable详解
Java 序列化Serializable详解(附详细例子) Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连 ...
- 各种Java序列化性能比较
转载:http://www.jdon.com/concurrent/serialization.html 这里比较Java对象序列化 XML JSON Kryo POF等序列化性能比较. 很多人以 ...
- 简述java序列化
1. 什么是Java对象序列化 Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期 ...
- 透过byte数组简单分析Java序列化、Kryo、ProtoBuf序列化
序列化在高性能网络编程.分布式系统开发中是举足轻重的之前有用过Java序列化.ProtocolBuffer等,在这篇文章这里中简单分析序列化后的byte数组观察各种序列化的差异与性能,这里主要分析Ja ...
- [转] Java序列化与反序列化
原文地址:http://blog.csdn.net/wangloveall/article/details/7992448 Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java ...
随机推荐
- Jquery:Jquery中的事件<二>
这几天快忙死了,办了离职还得办入职,完全打乱了我的计划,但是能有一个理想的工作,还是很开心的,以后加把劲,争取把计划再赶上来!不说了,学习!!! 五.事件对象的属性 1.event.type:获取事件 ...
- silverlight visifire控件图表制作——silverlight 后台方法打印
一.后台方法 1.添加引用:using System.Windows.Printing; 2.全局变量://定义图片和文本打印变量 PrintDocument printImage; 3.构造方法体 ...
- Qt将表格table保存为excel(odbc方式)
首先是保存excel的方法,可参照: http://dzmlmszp.blog.163.com/blog/static/179271962014819111812531/ ok,进入正题. 现在我有一 ...
- ibatis 更改resultmap后 java.sql.SQLException: Column 'del_status' not found.
当在resultmap中增加字段后,查询语句也必须增加相应字段,否则会报错, java.sql.SQLException: Column 'del_status' not found. 因为查询结果与 ...
- sqlalchemy操作Mysql
SQLAlchemy“采用简单的Python语言,为高效和高性能的数据库访问设计,实现了完整的企业级持久模型”.SQLAlchemy的理念是,SQL数据库的量级和性能重要于对象集合:而对象集合的抽象又 ...
- R语言的数据结构
首先声明,R语言对大小写敏感. 一.向量 vector类型可以存储数字.字符和逻辑类型.构建函数为C(): > a <- c(1,2,3,4) > b <- c('dau',' ...
- mac/unix系统:C++实现一个端口扫描器
在比较早以前,我用过S扫描器, 以及大名鼎鼎的nmap扫描器, 可以快速扫描某个主机开放的端口, 今天使用C实现这样一个软件, 编译环境为Mac, 系统版本10.11.6: #include < ...
- Redis使用(1)---安装
简介 Redis具体简介可以百度.它可以在Linux和Windows下运行,但官方只提供针对Linux的包,Windows对其也有自己的开发团队. redis官网:http://www.redis.i ...
- HTML5实战之桌面通知
桌面通知功能能够让浏览器即使是最小化状态也能将消息通知给用户.这和WebIM是最为天然的结合.不过,目前支持Desktop Notification功能的浏览器只有Chrome5+. 关于通知的基础知 ...
- 使用SALT-API进入集成开发的简单样例
测试的时候,可以CURL -K,但真正作集成的时候,却是不可以的. 必须,不可以让TOKEN满天飞吧. 现在进入这个阶段了.写个样例先: import salt import salt.auth im ...