JAVA 中进行网络通信时,通信的程序两端要传输的对象,不仅要序列化,而且这个对象所属的类的名字要完全一样,连包的名字都得一样

  如上图项目目录,这是一个简易的QQ,客户端登录的时候要传输用户信息到服务器验证,所以两端都会用到User类的对象,但一开始我在Server端的包名是com.qq.server.common,两端的报名字不一致,所以server端卡在了逆序列化那里:

User user=(User)ois.readObject();

  也就是说server端收到了传输过来的user对象,但是无法解析,当时报的错误有两种,(虽然当时知道了问题出在哪里,不知道为什么会报不同的错误,就在把这种迷惑记录在案的时候突然似乎明白了,在最下面有分析)

1、第一种情况是只有包1、2,没有包3,报下面的错误:(绿色线标出的是出错的代码,即User user=(User)ois.readObject(); )

java.lang.ClassNotFoundException: com.qq.common.User

at java.net.URLClassLoader.findClass(URLClassLoader.java:381)

at java.lang.ClassLoader.loadClass(ClassLoader.java:424)

at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)

at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

at java.lang.Class.forName0(Native Method)

at java.lang.Class.forName(Class.java:348)

at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:626)

at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1613)

at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)

at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)

at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)

at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)

at com.qq.server.model.MyQQServer.<init>(MyQQServer.java:20)

at com.qq.server.view.MyServerFrame.actionPerformed(MyServerFrame.java:37)

at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)

at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2346)

at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)

at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)

at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)

at java.awt.Component.processMouseEvent(Component.java:6525)

at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)

at java.awt.Component.processEvent(Component.java:6290)

at java.awt.Container.processEvent(Container.java:2234)

at java.awt.Component.dispatchEventImpl(Component.java:4881)

at java.awt.Container.dispatchEventImpl(Container.java:2292)

at java.awt.Component.dispatchEvent(Component.java:4703)

at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4898)

at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4533)

at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4462)

at java.awt.Container.dispatchEventImpl(Container.java:2278)

at java.awt.Window.dispatchEventImpl(Window.java:2750)

at java.awt.Component.dispatchEvent(Component.java:4703)

at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)

at java.awt.EventQueue.access$500(EventQueue.java:97)

at java.awt.EventQueue$3.run(EventQueue.java:709)

at java.awt.EventQueue$3.run(EventQueue.java:703)

at java.security.AccessController.doPrivileged(Native Method)

at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)

at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:86)

at java.awt.EventQueue$4.run(EventQueue.java:731)

at java.awt.EventQueue$4.run(EventQueue.java:729)

at java.security.AccessController.doPrivileged(Native Method)

at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)

at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)

at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)

at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)

at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)

at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)

at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)

at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

2、第二种情况是1、2、3包共存,这时还是用的包1、2,所以肯定还是报错的,但是却报下面的错,虽然出错的地方是一样的,但是一直没搞懂为什么上面报的是ClassNotFoundException,而下面报ClassCastException。

java.lang.ClassCastException: com.qq.common.User cannot be cast to com.qq.server.common.User

at com.qq.server.model.MyQQServer.<init>(MyQQServer.java:20)

at com.qq.server.view.MyServerFrame.actionPerformed(MyServerFrame.java:37)

at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)

at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2346)

at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)

at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)

at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)

at java.awt.Component.processMouseEvent(Component.java:6525)

at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)

at java.awt.Component.processEvent(Component.java:6290)

at java.awt.Container.processEvent(Container.java:2234)

at java.awt.Component.dispatchEventImpl(Component.java:4881)

at java.awt.Container.dispatchEventImpl(Container.java:2292)

at java.awt.Component.dispatchEvent(Component.java:4703)

at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4898)

at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4533)

at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4462)

at java.awt.Container.dispatchEventImpl(Container.java:2278)

at java.awt.Window.dispatchEventImpl(Window.java:2750)

at java.awt.Component.dispatchEvent(Component.java:4703)

at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)

at java.awt.EventQueue.access$500(EventQueue.java:97)

at java.awt.EventQueue$3.run(EventQueue.java:709)

at java.awt.EventQueue$3.run(EventQueue.java:703)

at java.security.AccessController.doPrivileged(Native Method)

at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)

at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:86)

at java.awt.EventQueue$4.run(EventQueue.java:731)

at java.awt.EventQueue$4.run(EventQueue.java:729)

at java.security.AccessController.doPrivileged(Native Method)

at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)

at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)

at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)

at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)

at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)

at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)

at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)

at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

  通过这两个错误的不同,也对序列化有了更深的认识,对于网络中传输过来的序列化的对象,我们虽然是从外面接收过来的,但是要想逆序列化,也就是识别出来,达到像是完全在本地操作的目的,通信的两端就要有完全一样的类库(类的完整名字是包括包的名字的,所以包名也得一直)。

  1、上面第一个错误是因为,在本地没有找到com.qq.common.User这个类(错误提示的很明了,而且这个错误是在server端抛出的,虚拟机在告诉你:我没有在Server中找到这个包,但当时却忽视了“抛错地点”,当时还想呢,那不在Client端明明有一个com.qq.common.User类吗,你为什么还抛出这样的错误提示啊,窃以为这是在一个项目里,Server和Client端在视觉上的离得如此的进,当时就没有在引包这个思路上想,归根结底还是对序列化理解的不透彻啊)。

  2、理解了1以及序列化,就很容易理解为什么会报上面第二个错误了,因为Server端在本地找到了com.qq.common.User,也就是说虚拟机能识别收到的对象是com.qq.common.User,但不允许逆序列化为com.qq.server.common.User,也就是说Server端虽然收到的是Object对象,但当虚拟机进行向下转型的时候(此时应该会进行逆序列化),发现了问题,也就是说,虚拟机收到了一只兔子,你现在让它“逆序列化并向下转型”为一只猫,它不知道该怎么做了,所以报错:ClassCastException。

时间: 2024-07-28 21:18:00

JAVA 中进行网络通信时,通信的程序两端要传输的对象,不仅要序列化,而且这个对象所属的类的名字要完全一样,连包的名字都得一样的相关文章

Java中字符串比较时==和equals的区别

==是比较两个字符串引用的地址是否相同,即是否指向同一个对象,而equals方法则比较字符串的内容是否相同. 例如String a = "abc"; String b = "abc"; a == b返回true,a.equals(b)同样返回true,这是为什么呢? 原来程序在运行时有一个字符串池,创建字符串时会先查找池中是否有相应的字符串,如果已经存在的话只需把引用指向它即可,如果没有则新建一个. 上例中创建a时,会在字符串池中首先创建一个"abc&qu

Java中Socket网络通信

目录 目录 网络协议信息 InetAddress类的应用 URL类的应用 基于TCP的Socket通信 基于UDP的socket通信 Socket通信总结 markdown编辑器快捷键 网络协议信息 TCP 传输控制协议(Transmission Control Protocol) IP 互联网协议(Internet Protocol) HTTP 超文本传输协议(默认端口号为80) FTP 文件传输协议(默认端口号为:21) Telnet (远程登录服务,默认端口号为:23) InetAddre

java中的编译时常量与运行时常量

常量是程序运行期间恒定不变的量,许多程序设计语言都有某种方式,向编译器告知一块数据是恒定不变的,例如C++中的const和Java中的final. 根据编译器的不同行为,常量又分为编译时常量和运行时常量,其实编译时常量肯定就是运行时常量,只是编译时常量在编译的时候就被执行计算,并带入到程序中一切可能用到它的计算式中. 以Java为例,static final int a = 1将是一个编译时常量,编译后的符号表中将找不到a,所有对a的引用都被替换成了1. 而static final int b

java中封装的理解 《黑马程序员》

封装是java中的一大特性,他能使程序变得更安全.可重用.易维护等很多的优点. public class FengZhuang { public static void main(String[] args){//main主入口方法 Person p = new Person();//实例化我们下面的person类 p.setName("小明");//通过开放方法我们给这个实例化对象的name属性进行赋值 p.setAge(30);//通过开放方法我们给这个实例化对象的age属性进行赋

Java中string 创建对象时 “”和null的区别

null和""的区别 问题一: null和""的区别 String s=null; string.trim()就会抛出为空的exception String s=""; string.trim()就不会抛,为什么? 答: NULL代表声明了一个空对象,根本就不是一个字符串. ""代表声明了一个对象实例,这个对象实例的值是一个长度为0的空字符串. NULL代表声明了一个空对象,对空对象做任何操作都不行的,除了=和== "

控制面板里找不到“应用程序服务器”这个项目,Windows XP中金蝶安装时无“应用程序服务器”的解决办法

要注意先安装IIS,再安装VS2008. 我们会经常在控制面板里找不到"应用程序服务器"这个项目.我们需要按照下面的步骤来操作就会Ok. 1.下载IIS6,放置到D盘根目录. 2.在运行里输入:c:\Windows\inf\sysoc.inf 即打开 找到 [Components]段. 添加:iis=iis2.dll,OcEntry,iis2.inf,,7 非常重要的是你需要删去:iis=iis.dll,OcEntry,iis2.inf,,7这一句. 保存关闭. 3.在运行里输入CMD

Java中写入文件时换行符用"\r\n"、"\n"、"\r"?

Java是一个跨平台的语言,因为如果想写一个跨平台的软件,有些东西就需要考虑,例如换行. \r: 叫回车 Carriage Return \n: 叫新行 New Line 他们都会造成换行,那么我们如何确定使用哪个呢?  通常建议使用line.separator的系统属性 System.getProperty("line.separator")来获取当前OS的换行符,可以在调试的情况下看到! 不过如果你是在写一个网络程序或者服务器程序,则需要硬编码为"\r\n",而

java中服务器启动时,执行定时任务

package com.ripsoft.util; import java.util.Calendar; import java.util.Timer; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class TimerListener implements ServletContextListener{ private Timer timer = nu

Java 中 HashMap 初始化时赋值

1.HashMap 初始化的文艺写法 HashMap 是一种常用的数据结构,一般用来做数据字典或者 Hash 查找的容器.普通青年一般会这么初始化:HashMap<String, String> map = new HashMap<String, String>();map.put("name", "test");  map.put("age", "20"); 看完这段代码,很多人都会觉得这么写太啰嗦了