【问题标题】:Serializing java.lang.class序列化 java.lang.class
【发布时间】:2012-07-07 10:40:34
【问题描述】:

在数据库中持久化 Class 对象时遇到问题。

我尝试使用对象ObjectArrayOutputStreamByteArrayOutputStream 将对象转换为字节数组,如下所示并将其持久化为字节数组:

Class klazz = getClassForClassDef();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(klazz);
baos.toByteArray();

但我收到如下所示的错误:

java.lang.ClassFormatError: Incompatible magic value 2901213189 in class file

我认为构造字节数组的方式有问题。但我不知道如何创建一个正确的.class 等效类对象。

【问题讨论】:

    标签: java reflection classloader binary-serialization


    【解决方案1】:

    如果您真的想存储Class 本身

    您可以在此处阅读更多信息:https://stackoverflow.com/a/2390763/1001027

    如果您尝试存储对象

    您正在使用Class 作为writeObject 方法的参数。而不是这个,你应该使用你拥有的实例。


    // write the class
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(objectToSerialize);
    
    // this you need to store
    byte[] data = baos.toByteArray();
    
    // read it again (just a test)
    ByteArrayInputStream bais = new ByteArrayInputStream(data);
    Object restored = new ObjectInputStream(bais).readObject();
    
    // write what came from the deserialization
    System.out.println(restored);
    

    在示例中,变量objectToSerialize 将保存要存储的对象。


    您确定要真正将 java 序列化对象存储到您的数据库中吗?有几个替代方案。您可以使用诸如 Hibernate 之类的 ORM 框架来创建正式模型。

    如果您认为这过于动态,您可以使用 XML 序列化,例如 XStream 甚至 JSON 序列化,这会很好,因为它们是可读格式,这意味着您可以看到真正存储的内容,而无需反序列化使用 Java 应用程序只是为了检查状态。

    【讨论】:

    • 好吧。实际上我的问题不是存储所有java序列化对象。但我需要在运行时加载存储在数据库中的类。我创建了一个模型来表示一个简单类的元数据。通过很少的编码,我设法通过使用元数据从模型中创建了 Class 对象。但我无法存储类对象并在运行时使用反射检索加载类。
    • 好的,这意味着您需要执行我在示例下方的注释// read it again (just a test) 下方发布的两行代码,其中数据将是从您的数据库字段中检索到的byte[]
    • 错误现在消失了。但我离我的目标还差得很远。这次我得到了一个 ClassNotFoundException。当它尝试加载持久的 Class 对象时,它无法找到它的 .class 等效项。让我尝试更多来加载它,可能正在使用一些类加载器技巧..
    【解决方案2】:

    要序列化一个对象,您必须将对象本身而不是它的类写入流。此外,对象实例必须实现Serializable 接口,并且其所有内部字段都应该是可序列化的或瞬态的。

    在你的代码中,你应该写oos.writeObject(obj);而不是oos.writeObject(klazz);,提供obj是你要保存的对象实例。

    但是,如果您尝试将 Java 对象存储到数据库中(我们说的是关系数据库,不是吗?)我会将对象映射到表,将其每个属性存储为列。这样你就可以使用 SQL 和列的值来执行搜索和连接,但是你不能索引二进制字段。

    【讨论】:

    • 对。但在我的情况下,其中一个字段是存储类并在运行时从该字段加载它。
    • 为什么要存储类本身?存储类名然后用Class.forName(...)加载类不是更好吗?
    【解决方案3】:

    .class 文件不是序列化的 Class 对象。这是完全不同的东西,您将无法使用任何简单的 Java 代码来生成它。但是,您为什么要这样做?您已经在磁盘上拥有了 .class 文件,这就是您的 Java 程序了解该类的方式。你为什么不直接复制那个.class 文件呢?这只是找到它来自哪里(什么 JAR)的问题。

    【讨论】:

    • 是的。我使用这个短语只是为了暗示我必须从 DB 字段加载类,就像我们从 .class 文件中一样。
    猜你喜欢
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多