我有两个简单的应用程序:客户端和服务器。客户端加密(简单AES)自定义对象,并通过TCP套接字(以字节为单位)将其发送到服务器。服务器解密这些字节并调用重新创建此对象的方法,如下所示:
private static Object getObjectFromBytes(byte[] credentials) throws IOException, ClassNotFoundException{
ByteArrayInputStream bis = new ByteArrayInputStream(credentials);
ObjectInput in = null;
Object credentialsObj = null;
try {
in = new ObjectInputStream(bis);
credentialsObj = in.readObject();
} finally {
bis.close();
in.close();
}
return credentialsObj;
}
在客户端,当我加密此对象时,它的类型为mds.hm5.client.ITU_Credentials
。在服务器端,当我正在解密它并转换回对象时,它应该是mds.hm5.tokenservice.ITU_Credentials
。相反,我得到以下异常:
java.lang.ClassNotFoundException: mds.hm5.client.ITU_Credentials
他正在通过旧的类路径查找此对象。为什么会发生这种情况?我该如何解决?
其他信息:
以下是我在客户端将此对象转换为字节数组的方法:
private static byte[] getBytesFromObject(Object credentials) throws IOException{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
byte[] newBytes = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(credentials);
newBytes = bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally {
out.close();
bos.close();
}
return newBytes;
}
我使用泛型类型Object
的原因是因为我将使用这些方法来转换/加密/解密多种类型。这是正确的方式吗?
答案 0 :(得分:3)
在客户端,当我加密此对象时,它的类型为mds.hm5.client.ITU_Credentials。
这就是序列化流中的内容。
在服务器端,当我正在解密它并转换回对象时,它应该是mds.hm5.tokenservice.ITU_Credentials。
不,不应该。它应该与你序列化时相同[除非你采取了某些神奇的步骤,显然你没有。如果没有这些神奇的步骤,就没有任何魔力,也没有任何东西可以将mds.hm5.client.ITU_Credentials
与mds.hm5.tokenservice.ITU_Credentials
连接起来。您有两个具有相同名称和不同包的不同类,每个位置一个。它们不一样。
他正在通过旧的类路径寻找这个对象。
您对CLASSPATH和包名称感到困惑。他们不是一回事。它正在通过其实际的包名来寻找这个对象。它还能做什么呢?
答案 1 :(得分:2)
对象输出流不会序列化类本身,而只序列化其状态(字段值)。接收者需要类路径上的类文件。
也可以转课。您必须找到(或编写)可以从您的连接加载类的类加载器。如果您有类文件的URL,那么您可以使用URLClassloader。然后,您不必将类添加到类路径中。
答案 2 :(得分:0)
您的客户端需要在其类路径中包含定义该对象的.class文件。你正在做的是序列化/反序列化实例,而不是类。
答案 3 :(得分:0)
后期,但将来可能对某人有用: 我想在客户端发送其包为 entities 的对象 Message ,但是在服务器端,此 Message 类未嵌套在 entities 包,因此引发了此异常。可能是愚蠢的,但我花了很多时间才弄清楚。