欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识

可以通过lookup()方法来查找/创建 昆山软件定制开发 在这个JVM中加载的特定的ObjectStreamClass

点击: 次  来源:宝鼎软件 时间:2017-06-01

原文出处: 天凉好个秋

媒介

对付Java的序列化,一直只知道只需要实现Serializbale这个接口就可以了,详细内部实现一直不是很相识,正好这次在反复造RPC的轮子的时候涉及到序列化问题,就抽时间看了下 Java序列化的底层实现,这篇文章算是这次的进修小结吧。

第一部门:What

Java序列化是指把Java工具生存为二进制字节码的进程,Java反序列化是指把二进制码从头转换成Java工具的进程。

那么为什么需要序列化呢?

第一种环境是:一般环境下Java工具的声明周期都比Java虚拟机的要短,实际应用中我们但愿在JVM遏制运行之后可以或许耐久化指定的工具,这时候就需要把工具举办序列化之后生存。

第二种环境是:需要把Java工具通过网络举办传输的时候。因为数据只可以或许以二进制的形式在网络中举办传输,因此当把工具通过网络发送出去之前需要先序列化成二进制数据,在吸收端读到二进制数据之后反序列化成Java工具。

第二部门:How

本部门以序列化到文件为例讲授Java序列化的根基用法。

package com.beautyboss.slogen;

import java.io.*;

/**
* Author : Slogen
* AddTime : 17/4/30
*/
public class SerializableTest {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("temp.out");
ObjectOutputStream oos = new ObjectOutputStream(fos);
TestObject testObject = new TestObject();
oos.writeObject(testObject);
oos.flush();
oos.close();

FileInputStream fis = new FileInputStream("temp.out");
ObjectInputStream ois = new ObjectInputStream(fis);
TestObject deTest = (TestObject) ois.readObject();
System.out.println(deTest.testValue);
System.out.println(deTest.parentValue);
System.out.println(deTest.innerObject.innerValue);
}
}

class Parent implements Serializable {

private static final long serialVersionUID = -4963266899668807475L;

public int parentValue = 100;
}

class InnerObject implements Serializable {

private static final long serialVersionUID = 5704957411985783570L;

public int innerValue = 200;
}

class TestObject extends Parent implements Serializable {

private static final long serialVersionUID = -3186721026267206914L;

public int testValue = 300;

public InnerObject innerObject = new InnerObject();
}

措施执行完用vim打开temp.out文件,可以看到

0000000: aced 0005 7372 0020 636f 6d2e 6265 6175 ....sr. com.beau
0000010: 7479 626f 7373 2e73 6c6f 6765 6e2e 5465 tyboss.slogen.Te
0000020: 7374 4f62 6a65 6374 d3c6 7e1c 4f13 2afe stObject..~.O.*.
0000030: 0200 0249 0009 7465 7374 5661 6c75 654c ...I..testValueL
0000040: 000b 696e 6e65 724f 626a 6563 7474 0023 ..innerObjectt.#
0000050: 4c63 6f6d 2f62 6561 7574 7962 6f73 732f Lcom/beautyboss/
0000060: 736c 6f67 656e 2f49 6e6e 6572 4f62 6a65 slogen/InnerObje
0000070: 6374 3b78 7200 1c63 6f6d 2e62 6561 7574 ct;xr..com.beaut
0000080: 7962 6f73 732e 736c 6f67 656e 2e50 6172 yboss.slogen.Par
0000090: 656e 74bb 1eef 0d1f c950 cd02 0001 4900 ent......P....I.
00000a0: 0b70 6172 656e 7456 616c 7565 7870 0000 .parentValuexp..
00000b0: 0064 0000 012c 7372 0021 636f 6d2e 6265 .d...,sr.!com.be
00000c0: 6175 7479 626f 7373 2e73 6c6f 6765 6e2e autyboss.slogen.
00000d0: 496e 6e65 724f 626a 6563 744f 2c14 8a40 InnerObjectO,..@
00000e0: 24fb 1202 0001 4900 0a69 6e6e 6572 5661 $.....I..innerVa
00000f0: 6c75 6578 7000 0000 c8 luexp....

第三部门:Why

挪用ObjectOutputStream.writeObject()和ObjectInputStream.readObject()之后毕竟做了什么?temp.out文件中的二进制别离代表什么意思?

别急,软件开发,且听我娓娓道来。

1. ObjectStreamClass类

官方文档对这个类的先容如下

Serialization’s descriptor for classes. It contains the name and serialVersionUID of the class. The ObjectStreamClass for a specific class loaded in this Java VM can be found/created using the lookup method.

可以看到ObjectStreamClass这个是类的序列化描写符,这个类可以描写需要被序列化的类的元数据,包罗被序列化的类的名字以及序列号。可以通过lookup()要领来查找/建设在这个JVM中加载的特定的ObjectStreamClass工具。

2. 序列化:writeObject()

在挪用wroteObject()举办序列化之前会先挪用ObjectOutputStream的结构函数生成一个ObjectOutputStream工具,结构函数如下:

public ObjectOutputStream(OutputStream out) throws IOException {
    verifySubclass();
    // bout暗示底层的字节数据容器
    bout = new BlockDataOutputStream(out);
    handles = new HandleTable(10, (float) 3.00);
    subs = new ReplaceTable(10, (float) 3.00);
    enableOverride = false;
    writeStreamHeader(); // 写入文件头
    bout.setBlockDataMode(true); // flush数据
    if (extendedDebugInfo) {
        debugInfoStack = new DebugTraceInfoStack();
    } else {
        debugInfoStack = null;
    }
}