【问题标题】:Reading an unkown serialized object in Java在 Java 中读取未知的序列化对象
【发布时间】:2013-08-30 16:24:40
【问题描述】:

我有一个服务器崩溃了(如果你想知道我的世界),一些宝贵的数据被保存在一个序列化的目标文件中。我没有成功用 Java 的 ObjectInputStream 读取它。这是我在网上找到的一段代码,稍微编辑了一下。当我读取对象时,它会抛出 ClassNotFoundException。

//Part of it
ObjectInputStream objStream = new ObjectInputStream(new FileInputStream(f));
Object obj = objStream.readObject();
System.out.println("The Object : "+  obj);
objStream.close();
System.out.println("Deserializing Operation Completly Successfully.");

问题是我根本不知道它的内容。我怎么知道这个对象中包含哪些字段和方法?

java.lang.ClassNotFoundException: net.****.****.****.**** //CENSORED
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:249)
at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:602)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1589)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1494)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1748)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1327)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:349)
at java.util.ArrayList.readObject(ArrayList.java:593)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:979)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1775)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1327)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:349)
at main.ReadFile.main(ReadFile.java:28)

编辑:我已经反编译了它,并将它的所有包添加到我的 src 中。成功读取对象。但这并不能回答问题,问题仍然存在;“如何在 Java 中读取未知的序列化对象。”。

【问题讨论】:

  • 请附上错误的完整堆栈跟踪。
  • 如果你已经成功读取了对象,你没有得到ClassNotFoundException,所以你的问题没有什么可以回答了。

标签: java object serialization


【解决方案1】:

您可以使用Reflection 来提取对象的内容,但这不是很方便。

但是,如果您知道反序列化后期望什么类,那么您可以向下转换为特定类型。

在运行时找出对象的类可以这样完成:

Object obj = objStream.readObject();
Class<?> clazz = obj.getClass();
System.out.println(clazz.getName());

假设,如果打印 x.y.Person,那么您可以修改您的程序以使用该具体类:

import x.y.Person;

Person person = (Person) objStream.readObject();
System.out.println(person.getName());

如果类不可用,可以尝试使用jdeserialize提取序列化流的内容。

【讨论】:

  • 好吧,当你写我已经设法用Javas ObjectInputStream 阅读它时,我认为没有错误。您也应该在问题中包含错误消息。
  • 我没有注意到错误,因为我用来测试的原始代码使用 System.out.println 来解决错误,这让我没有意识到有错误。
  • 这还有可能吗?或者我必须在源代码中包含原始类才能执行此操作?
  • @Louise 缺少哪个课程?
  • 这是一个我没有的外来类,我没有这个对象源代码的原始类。
【解决方案2】:

Java 的序列化 API 假定这些类型在反序列化时可用。 design 依赖于此。

可能能够使用Grammar for the Stream Format 为API 类型编写自己的解析器。

存在没有字段信息的情况

例如,以下Serializable 类型不提供任何字段元数据,其内部编写为blockdata

public class ContrivedType implements Serializable {
  public String foo;
  public int bar;

  private void writeObject(java.io.ObjectOutputStream out) throws IOException {
    out.writeObject(foo);
    if (foo != null) {
      out.writeInt(bar);
    }
  }

  private void readObject(java.io.ObjectInputStream in) throws IOException,
      ClassNotFoundException {
    foo = (String) in.readObject();
    bar = foo != null ? in.readInt() : 0;
  }
}

类型的数据结构封装在类型本身中。

如果 API 有 javadoc,它应该提供一些信息作为 serialized form 文档的一部分。

【讨论】:

    猜你喜欢
    • 2011-05-17
    • 2016-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多