Java序列化的机制和原理

Java序列化的机制和原理
Java序列化的机制和原理

Java序列化的机制和原理

有关Java对象的序列化和反序列化也算是Java基础的一部分,下面对Java序列化的机制和原理进行一些介绍。

Java序列化算法透析

Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化deserialization 是一种将这些字节重建成一个对象的过程。Java序列化API提供一种处理对象序列化的标准机制。在这里你能学到如何序列化一个对象,什么时候需要序列化以及Java序列化的算法,我们用一个实例来示范序列化以后的字节是如何描述一个对象的信息的。

序列化的必要性

Java中,一切都是对象,在分布式环境中经常需要将Object从这一端网络或设备传递到另一端。这就需要有一种可以在两端传输数据的协议。Java序列化机制就是为了解决这个问题而产生。

如何序列化一个对象

一个对象能够序列化的前提是实现Serializable接口,Serializable接口没有方法,更像是个标记。有了这个标记的Class就能被序列化机制处理。

1.import java.io.Serializable;

2.

3.class TestSerial implements Serializable {

4.

5.public byte version = 100;

6.

7.public byte count = 0;

8.

9.}

然后我们写个程序将对象序列化并输出。ObjectOutputStream能把Object输出成Byte 流。我们将Byte流暂时存储到temp.out文件里。

1.public static void main(String args[]) throws IOException {

2.

3. FileOutputStream fos = new FileOutputStream("temp.out

");

4.

5. ObjectOutputStream oos = new ObjectOutputStream(fos);

6.

7. TestSerial ts = new TestSerial();

8.

9. oos.writeObject(ts);

10.

11. oos.flush();

12.

13. oos.close();

14.

15.}

如果要从持久的文件中读取Bytes重建对象,我们可以使用ObjectInputStream。

1.public static void main(String args[]) throws IOException {

2.

3. FileInputStream fis = new FileInputStream("temp.out")

;

4.

5. ObjectInputStream oin = new ObjectInputStream(fis);

6.

7. TestSerial ts = (TestSerial) oin.readObject();

8.

9. System.out.println("version="+ts.version);

10.

11.}

执行结果为

100.

对象的序列化格式

将一个对象序列化后是什么样子呢?打开刚才我们将对象序列化输出的temp.out文件,以16进制方式显示。内容应该如下:

AC ED 00 05 73 72 00 0A 53 65 72 69 61 6C 54 65 73 74 A0 0C 34 00 FE B1 DD F9 02 00 02 42 00 05 63 6F 75 6E 74 42 00 07 76 65 72 73 69 6F 6E 78 70 00 64

这一坨字节就是用来描述序列化以后的

TestSerial对象的,我们注意到TestSerial类中只有两个域:

public byte version = 100;

public byte count = 0;

且都是byte型,理论上存储这两个域只需要2个byte,但是实际上temp.out占据空间为51bytes,也就是说除了数据以外,还包括了对序列化对象的其他描述。

Java的序列化算法

序列化算法一般会按步骤做如下事情:

◆将对象实例相关的类元数据输出。

◆递归地输出类的超类描述直到不再有超类。

◆类元数据完了以后,开始从最顶层的超类开始输出对象实例的实际数据值。

◆从上至下递归输出实例的数据

我们用另一个更完整覆盖所有可能出现的情况的例子来说明:

1.class parent implements Serializable {

2.

3.int parentVersion = 10;

4.

5.}

6.

7.

8.

9.class contain implements Serializable{

10.

11.int containVersion = 11;

12.

13.}

14.

15.public class SerialTest extends parent implements Serializab

le {

16.

17.int version = 66;

18.

19. contain con = new contain();

20.

21.

22.

23.public int getVersion() {

24.

25.return version;

26.

27. }

28.

29.public static void main(String args[]) throws IOExcep

tion {

30.

31. FileOutputStream fos = new FileOutputStream("t

emp.out");

32.

33. ObjectOutputStream oos = new ObjectOutputStrea

m(fos);

34.

35. SerialTest st = new SerialTest();

36.

37. oos.writeObject(st);

38.

39. oos.flush();

40.

41. oos.close();

42.

43. }

44.

45.}

这个例子是相当的直白啦。SerialTest类实现了Parent超类,内部还持有一个Container 对象。

序列化后的格式如下:

AC ED 00 05 73 72 00 0A 53 65 72 69 61 6C 54 65

73 74 05 52 81 5A AC 66 02 F6 02 00 02 49 00 07

76 65 72 73 69 6F 6E 4C 00 03 63 6F 6E 74 00 09

4C 63 6F 6E 74 61 69 6E 3B 78 72 00 06 70 61 72

65 6E 74 0E DB D2 BD 85 EE 63 7A 02 00 01 49 00

0D 70 61 72 65 6E 74 56 65 72 73 69 6F 6E 78 70

00 00 00 0A 00 00 00 42 73 72 00 07 63 6F 6E 74

61 69 6E FC BB E6 0E FB CB 60 C7 02 00 01 49 00

0E 63 6F 6E 74 61 69 6E 56 65 72 73 69 6F 6E 78

70 00 00 00 0B

我们来仔细看看这些字节都代表了啥。开头部分,见颜色:

1.AC ED: STREAM_MAGIC. 声明使用了序列化协议.

2.00 05: STREAM_VERSION. 序列化协议版本.

3.0x73: TC_OBJECT. 声明这是一个新的对象.

序列化算法的第一步就是输出对象相关类的描述。例子所示对象为SerialTest类实例,因此接下来输出SerialTest类的描述。见颜色:

1.0x72: TC_CLASSDESC. 声明这里开始一个新Class。

2.00 0A: Class

java序列化的作用

最近在阅读Core J2EE Patterns 的时候发现例子里用于在各个层次里进行传输的TO(Data Transfer Object)都实现了java.io.Serializable接口,看到这些偶突然感到茅塞顿开~困扰了很久的关于Serializable的疑问渐渐解开了,查找相关资料并总结如下: 序列化是什么: 序列化就是将一个对象的状态(各个属性量)保存起来,然后在适当的时候再获得。 序列化分为两大部分:序列化和反序列化。序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例 序列化的什么特点: 如果某个类能够被序列化,其子类也可以被序列化。声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态, transient代表对象的临时数据。 什么时候使用序列化: 一:对象序列化可以实现分布式对象。主要应用例如:RMI要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样。 二:java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用对象序列化可以进行对象的"深复制",即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。 ====================== 可以看看接口java.io.serializable的中文解释: Serializable public interface Serializable 类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。

类的加载

类从加载到虚拟机到卸载,它的整个生命周期包括:加载(Loading),验证(Validation),准备(Preparation),解析(Resolution),初始化(Initialization),使用(Using)和卸载(Unloading)。其中,验证、准备和解析部分被称为连接(Linking)。 加载: 在加载阶段,虚拟机主要完成三件事: 1.通过一个类的全限定名来获取定义此类的二进制字节流。 2.将这个字节流所代表的静态存储结构转化为方法区域的运行时数据结构。 3.在Java堆中生成一个代表这个类的https://www.360docs.net/doc/4d16968926.html,ng.Class对象,作为方法区域数据的访问入口。 验证: 验证阶段作用是保证Class文件的字节流包含的信息符合JVM规范,不会给JVM造成危害。如果验证失败,就会抛出一个https://www.360docs.net/doc/4d16968926.html,ng.VerifyError异常或其子类异常。验证过程分为四个阶段: 1.文件格式验证:验证字节流文件是否符合Class文件格式的规范,并且能被当前虚拟机正确的处理。 2.元数据验证:是对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言的规范。 3.字节码验证:主要是进行数据流和控制流的分析,保证被校验类的方法在运行时不会危害虚拟机。

4.符号引用验证:符号引用验证发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在解析阶段中发生。 准备: 准备阶段为变量分配内存并设置类变量的初始化。在这个阶段分配的仅为类的变量(static修饰的变量),而不包括类的实例变量。对已非final的变量,JVM会将其设置成“零值”,而不是其赋值语句的值: pirvate static int size = 12; 那么在这个阶段,size的值为0,而不是12。final修饰的类变量将会赋值成真实的值。 解析: 解析过程是将常量池内的符号引用替换成直接引用。主要包括四种类型引用的解析。类或接口的解析、字段解析、方法解析、接口方法解析。 初始化: 在准备阶段,类变量已经经过一次初始化了,在这个阶段,则是根据程序员通过程序制定的计划去初始化类的变量和其他资源。这些资源有static{}块,构造函数,父类的初始化等。 至于使用和卸载阶段阶段,这里不再过多说明,使用过程就是根据程序定义的行为执行,卸载由GC完成。

JAVA序列化基础知识Serializable与Externalizable的区别

大家都知道Serializable是一个mark interface,告诉JVM这个对象可以被转换成二进制流来传输. 但是Serializable与Externalizable的转换二进制流的过程是不一样的. Serializable 在我们实现这个接口的时候,我们可以使用4个私有方法来控制序列化的过程: 我们来看一个例子: public class FooImpl implements java.io.Serializable{ private String message; public String getFoo() { return message; } public void setMessage(String message) { this.message = message; } private void writeObject(java.io.ObjectOutputStream out) throws IOException { System.out.println("writeObject invoked"); out.writeObject(this.message == null ? "hohohahaha" : this.message); } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { System.out.println("readObject invoked"); this.message = (String) in.readObject(); System.out.println("got message:" + message); } private Object writeReplace() throws ObjectStreamException { System.out.println("writeReplace invoked"); return this; } private Object readResolve() throws ObjectStreamException { System.out.println("readResolve invoked"); return this; }

【IT专家】来自加载类的Java Call类函数

本文由我司收集整编,推荐下载,如有疑问,请与我司联系 来自加载类的Java Call类函数 2011/02/25 1277 How would I, if possible, call a function in my Main class in the class that I load? (I know that is impossible to understand, so I’ll explain) ?如果可能的话,我如何在我加载的类中调用Main类中的函数? (我知道这是不可能理解的,因此我会解释) I.E: public class SomeClass public SomeClass //load a class here public void FuncToCall() {}//In a separate file, dynamically loaded.public class LoadedClass public LoadedClass //Call a function in the class that loads this SomeClass.FuncToCall(); So I would end up having 2 files: SomeClass.class and LoadedClass.class. I guess my main question is, how do I reference SomeClass in LoadedClass? ?因此我最终会得到2个文件:SomeClass.class和LoadedClass.class。我想我的主要问题是,如何在LoadedClass中引用SomeClass? **EDIT: So maybe I should better explain the use case. A java program dynamically loads the “SomeClass” script from a folder. The script then downloads a .jar file from the internet and opens and runs the “LoadedClass” script within that. How do I use functions in SomeClass in LoadedClass if SomeClass isn’t in the same .jar or in a .jar at all? ?因此也许我应该更好地解释用例。java程序从文件夹动态加载“SomeClass”脚本。然后,该脚本从Internet下载.jar文件,并在其中打开并运行“LoadedClass”脚本。如果SomeClass不在同一个.jar或.jar中,我如何在LoadedClass中的SomeClass中使用函数? ?你这样做.. ?If they are in different packages you have to either import the class or use the fully qualified name. ?如果它们位于不同的包中,则必须导入该类或使用完全限定的名称。

java如何写存储过程

Java中对存储过程的调用 一:Java如何实现对存储过程的调用: A:不带输出参数的 ---------------不带输出参数的---------------------------------- create procedure getsum @n int =0<--此处为参数--> as declare @sum int<--定义变量--> declare @i int set @sum=0 set @i=0 while @i<=@n begin set @sum=@sum+@i set @i=@i+1 end print 'the sum is '+ltrim(rtrim(str(@sum))) --------------在SQL中执行:-------------------- exec getsum 100 ------------在JAVA中调用:--------------------- JAVA可以调用但是在JAVA程序却不能去显示该存储过程的结果因为上面的存储 过程的参数类型int 传递方式是in(按值)方式 import java.sql.*; public class ProcedureTest { public static void main(String args[]) throws Exception { //加载驱动 DriverManager.registerDriver(new sun.jdbc.odbc.JdbcOdbcDriver()); //获得连接 Connection conn=DriverManager.getConnection("jdbc:odbc:mydata","sa",""); //创建存储过程的对象 CallableStatement c=conn.prepareCall("{call getsum(?)}"); //给存储过程的参数设置值 c.setInt(1,100); //将第一个参数的值设置成100 //执行存储过程 c.execute(); conn.close();

将php序列化到数据库的对象饭序列化成java对象

将php序列化到数据库的对象饭序列化成java对象 php的对象序列化到数据库中,形如 a:3:{i:0;i:1241;i:1;i:4;i:2;i:16;}但是java需要取出这样的对象,转换成java的对象/* PHPSerializer.java * * Author: Ma Bingyao * Copyright: https://www.360docs.net/doc/4d16968926.html, * Version: 2.1 * LastModified: 2006-08-09 * This library is free. You can redistribute it and/or modify it. * https://www.360docs.net/doc/4d16968926.html,/?p=202 */ package org.phprpc.util; import java.io.*; import java.util.*; import https://www.360docs.net/doc/4d16968926.html,ng.reflect.*;

class UnSerializeResult { public Object value; public int hv; public UnSerializeResult() {} public UnSerializeResult(Object value, int hv) { this.value = value; this.hv = hv; } } public class PHPSerializer { private static Package[] __packages = Package.getPackages(); private static final byte __Quote = 34; private static final byte __0 = 48; private static final byte __1 = 49; private static final byte __Colon = 58; private static final byte __Semicolon = 59; private static final byte __C = 67; private static final byte __N = 78;

Java的数据结构相关的类实现原理

Java的数据结构相关的类实现原理 List接口 List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。 和下面要提到的Set不同,List允许有相同的元素。 除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素,还能向前或向后遍历。 实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。 LinkedList List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。 此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。 所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。 注意,此实现不是同步的。如果多个线程同时访问一个链接列表,而其中至少一个线程从结构上修改了该列表,则它必须保持外部同步。(结构修改指添加或删除一个或多个元素的任何操作;仅设置元素的值不是结构修改。)这一般通过对自然封装该列表的对象进行同步操作来完成。如果不存在这样的对象,则应该使 用 Collections.synchronizedList 方法来“包装”该列表。最好在创建时完成这一操作,以防止对列表进行意外的不同步访问,如下所示: List list = Collections.synchronizedList(new LinkedList(...)); 此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:在迭代器创建之后,如果从结构上对列表进行修改,除非通过迭代器自身的remove 或 add 方法,其他任何时间任何方式的修改,迭代器都将抛 出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不冒将来不确定的时间任意发生不确定行为的风险。 注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何硬性保证。快速失败迭代器尽最大努力抛出ConcurrentModificationException。因此,编写依赖于此异常的程序的方式是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测程序错误。 ArrayList

Java-Jackson反序列化漏洞及挖洞思路

源码分析Jackson反序列化漏洞 前言: 本次分析从Java序列化和反序列化源码开始分析,进一步分析Jackson源码,找出造成漏洞的原因,最后以Jackson2.9.2版本,JDK1.80_171,resin4.0.52,CVE-2020-10673为例复现漏洞。 一.JA V A反序列化原理 1.1 Class对象 每一个类都有一个Class对象,Class对象包含每一个类的运行时信息,每一个类都有一个Class对象,每编译一个类就产生一个Class对象,Class类没有公共的构造方法,Class对象是在类加载的时候由JVM以及通过调用类加载器中的DefineClass()方法自动构造的,因此不能显式地声明一个Class对象。在类加载阶段,类加载器首先检查这个类的Class对象是否已经被加载。如果尚未加载,默认的类加载器就会根据类的全限定名查找.class文件。一旦某个类的Class对象被载入内存,我们就可以它来创建这个类的所有对象以及获得这个类的运行时信息。 获得Class对象的方法: 1).Class.forName(“类的全名”);//com.xx.xx.xx 2).实例对象.getClass() 3).类名.class 1.2反射 JA V A反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

实现Java反射机制的类都位于https://www.360docs.net/doc/4d16968926.html,ng.reflect包中: 1).Class类:代表一个类 2).Field类:代表类的成员变量(类的属性) 3).Method类:代表类的方法 4).Constructor类:代表类的构造方法 5).Array类:提供了动态创建数组,以及访问数组的元素的静态方法 简单反射调用代码 Class clz=this.getClass(); Object obj= clz.getMethod("方法名",Class对象序列).invoke(this,Object参数序列); 1.3 反序列化 Java 序列化是指把Java 对象转换为字节序列的过程便于保存在内存、文件、数据库中,ObjectOutputStream类的writeObject() 方法可以实现序列化。 Java 反序列化是指把字节序列恢复为Java 对象的过程,ObjectInputStream 类的readObject() 方法用于反序列化。 RMI:是Java 的一组拥护开发分布式应用程序的API,实现了不同操作系统之间程序的方法调用。值得注意的是,RMI 的传输100% 基于反序列化,Java RMI 的默认端口是1099 端口。 JMX:JMX 是一套标准的代理和服务,用户可以在任何Java 应用程序中使用这些代理和服务实现管理,中间件软件WebLogic 的管理页面就是基于JMX 开发的,而JBoss 则整个系统都基于JMX 构架。 只有实现了Serializable接口的类的对象才可以被序列化,Serializable 接口是启用其序列化功能的接口,实现java.io.Serializable 接口的类才是可序列化的,没有实现此接口的类将不能使它们的任一状态被序列化或逆序列化。 readObject() 方法的作用正是从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回,readObject() 是可以重写的,可以定制反序列化的一些行为。 readObject()主要做的事情,其实就是读取正常应该被序列化的字段信息后,

Java程序是如何运行的

Java程序是如何运行的 JVM是Java的运行时虚拟机,所有的Java程序都是在JVM沙箱中运行,每个Java程序就是一个独立的JVM进程。 谈到Java程序是如何运行的,首先需要理解的肯定是JVM是如何运行的,什么是JVM;要理解我们编写的Java程序,运行起来以后到底是什么样子,本质上就是弄清楚JVM是什么样子。 Java程序的代码是什么样的 Java诞生之初最大的卖点就是编写的代码跨平台可移植性,实现这种可移植性,是因为Java通过平台特定的虚拟机,运行中间的字节码,而不是直接编译成本地二进制代码实现,中间字节码也就是java文件编译后生成的.class文件,Jar包的话,实际上只是一系列.class文件的集合。 编写Java程序,首先需要一个入口点,在运行的时候通过指定MainClass来指定入口点,代码层面主类必须实现一个静态的main函数,运行时虚拟机会从MainClass.main开始执行指令,其他的逻辑只是import和函数调用了。 SDK自带的javac命令,负责将我们编程的Java代码,也就是.java文件,编译成平台无关的字节码;字节码可以在任何操作系统平台上,通过平台对应的JVM执行;JVM执行的时候,运行字节码,根据自己的平台特性,将字节码转换成平台相关的二进制码运行。 javac编译器运行的过程大致分为:词法分析(Token流)、语法分析(语法树)、语义分析(注解语法树),还有代码生成器,根据注解语法树,生成字节码, 语义分析阶段,编译器会做一些操作,将人类友好的代码,做一些处理,转换成更符合机器执行机制的代码,例如全局变量,魔法变量,依赖注入,注解这些魔法机制。大致分为以下步骤: 1. 给类添加默认构造函数 2. 处理注解 3. 检查语义的合法性并进行逻辑判断 4. 数据流分析 5. 对语法树进行语义分析(变量自动转换并去掉语法糖) JVM是什么 JVM = 类加载器 classloader + 执行引擎 execution engine + 运行时数据区域 runtime data area JVM就是运行编译好字节码的虚拟机,不同的操作系统和平台上,虚拟机将平台无关的字节码,编译成特定平台的指令去执行。我觉得,JVM首先是一个独立运行在操作系统上的进程。执行java命

Java架构学习【JVM与性能优化知识点整理】编写高效优雅Java程序

面向对象 构造器参数太多怎么办? 用builder模式,用在 1、5个或者5个以上的成员变量 2、参数不多,但是在未来,参数会增加 Builder模式: 属于对象的创建模式,一般有 1.抽象建造者:一般来说是个接口,包含1)建造方法,建造部件的方法(不止一 个),2)返回产品的方法 2.具体建造者 3.导演者,调用具体的建造者,创建产品对象 4.产品,需要建造的复杂对象 对于客户端,创建导演者和具体建造者,并把具体建造者交给导演者,然后由客户端通知导演者操纵建造者进行产品的创建。 在实际的应用过程中,有时会省略抽象建造者和导演者。 不需要实例化的类应该构造器私有 如,一些工具类提供的都是静态方法,这些类是不应该提供具体的实例的。可以参考JDK 中的Arrays。 不要创建不必要的对象 1.避免无意中创建的对象,如自动装箱 2.可以在类的多个实例之间重用的成员变量,尽量使用static。

但是,要记住,是不要创建不必要的对象,而不是不要创建对象。 对象池要谨慎使用,除非创建的对象是非常昂贵的操作,如数据库的连接,巨型对象等等。 避免使用终结方法 finalizer方法,jdk不能保证何时执行,也不能保证一定会执行。如果有确实要释放的资源应该用try/finally。 使类和成员的可访问性最小化 编写程序和设计架构,最重要的目标之一就是模块之间的解耦。使类和成员的可访问性最小化无疑是有效的途径之一。 使可变性最小化 尽量使类不可变,不可变的类比可变的类更加易于设计、实现和使用,而且更不容易出错,更安全。 常用的手段: 不提供任何可以修改对象状态的方法; 使所有的域都是final的。 使所有的域都是私有的。 使用写时复制机制。带来的问题:会导致系统产生大量的对象,而且性能有一定的影响,需要在使用过程中小心权衡。 复合优先于继承 继承容易破坏封装性,而且会使子类的实现依赖于父类。 复合则是在类中增加一个私有域,引用类的一个实例,这样的话就避免了依赖类的具体实现。 只有在子类确实是父类的一个子类型时,才比较适合用继承。 接口优于抽象类 java是个单继承的,但是类允许实现多个接口。

java序列化原理与算法

Java序列化原理和算法 总结: java中序列化算法的顺序: 1、子类的类信息描述 2、子类的字段信息描述(如果遇到类对象的属性,暂时用string的指针表示) 3、父类的类信息描述 4、父类的字段信息描述 5、对父类的字段信息进行赋值 6、对子类的字段信息进行赋值 7、发现子类的字段为类对象时,描述该类对象,并查找该类对象的父类,以以上方式描述,然后赋值。 本文讲解了Java序列化的机制和原理。从文中你可以了解如何序列化一个对象,什么时候需要序列化以及Java序列化的算法。 有关Java对象的序列化和反序列化也算是Java基础的一部分,下面对Java序列化的机制和原理进行一些介绍。 Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化deserialization 是一种将这些字节重建成一个对象的过程。Java序列化API提供一种处理对象序列化的标准机制。在这里你能学到如何序列化一个对象,什么时候需要序列化以及Java序列化的算法,我们用一个实例来示范序列化以后的字节是如何描述一个对象的信息的。 序列化的必要性 Java中,一切都是对象,在分布式环境中经常需要将Object从这一端网络或设备传递到另一端。 这就需要有一种可以在两端传输数据的协议。Java序列化机制就是为了解决这个问题而产生。如何序列化一个对象 一个对象能够序列化的前提是实现Serializable接口,Serializable接口没有方法,更像是个标记。 有了这个标记的Class就能被序列化机制处理。 import java.io.Serializable; class TestSerial implements Serializable { public byte version = 100; public byte count = 0; } 然后我们写个程序将对象序列化并输出。ObjectOutputStream能把Object输出成Byte流。 我们将Byte流暂时存储到temp.out文件里。 public static void main(String args[]) throws IOException { FileOutputStream fos = new FileOutputStream("temp.out");

java类加载机制

Java类加载机制(一) 译:ayi 第一次翻译,翻译得不是很好,请多多指点 我的邮箱:nonopo12345@https://www.360docs.net/doc/4d16968926.html, 原文:https://www.360docs.net/doc/4d16968926.html,/pub/a/onjava/2005/01/26/classloading.html 类加载是java特性的一个重量级的组成部分。尽管,java中“advanced topics”的发展,使java的类加载机制的地位有所下降。但每位编程着都应该知道这部分的工作机制,以及怎样去更好与其配合。这可以使我们节省很多时间,二不必要浪费在调试ClassNotFoundException, ClassCastException, 等。 这篇文章将从最基本的开始,比如代码和数据的关系和区别,以及他们怎么样关系起来形成一个实例或者对象。然后将会说到,java中怎样通过类加载器把代码加载到JVM中,以及java中实现的主要的几种类型的类加载器。然后在这篇文章中我们将会了解到java类加载机制的内幕,我们将使用最基本的代码来描述,这些代码执行与类加载器之后,但在加载一个类之前。在接下来的部分将使用一些例子来强调,对于开发者继承和开发自己的类加载器的必要性。接着将告诉你们怎样编写自己的类加载器,以及怎样使用它们去创建一个一般的能加载包括远程客户端辅助代码的类加载器引擎,以及怎样把它在JVM中定义,实例化,然后执行。习惯上,把J2EE-specific components 中说明的作为java类加载的规范,这篇文章正是从这本手册总结来的。 类和数据 一个类代表一段要执行的代码,然而数据则代表与这些代码相关联的某种状态。状态可以改变,代码不能改变。我们把一种特定状态与一个类关联起来时,就得到了这个类的一个实例。所以同一个类的不同实例有不同的状态,但都参照相同的代码。在java中,一个类通常它的代码就包含在一个 .class 文件中,虽然其中也包括异常。然而,在java运行时,每个类都会构造一个超类对象(first-class object),它们其实是https://www.360docs.net/doc/4d16968926.html,ng.Class的实例。不论何时编译一个java文件,编译器都会在编译后的字节码中嵌入一个public, static, final型的字段class,这个字段表示的就是一个https://www.360docs.net/doc/4d16968926.html,ng.Class型的实例。因为它是public类型的,我们可以通过标识符来访问它,像这样: https://www.360docs.net/doc/4d16968926.html,ng.Class klass = Myclass.class; 只要一个类被加载到JVM,相同的类(强调:相同的类)将不会被重复加载。这将产生一个问题,什么才是相同的类?一个对象有一种特定状态和标识,对象总是与它所属类联系在一起,与这种状况相似,一个被加载到JVM中类也有特定的标识,接下来我们就阐述: 在java中,一个类通过认证的类全名来唯一标识。认证的类全名是由包名和类名两部分组

Java序列化的机制和原理

Java序列化的机制和原理 有关Java对象的序列化和反序列化也算是Java基础的一部分,下面对Java序列化的机制和原理进行一些介绍。 Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化deserialization 是一种将这些字节重建成一个对象的过程。Java序列化API提供一种处理对象序列化的标准机制。在这里你能学到如何序列化一个对象,什么时候需要序列化以及Java序列化的算法,我们用一个实例来示范序列化以后的字节是如何描述一个对象的信息的。 序列化的必要性 Java中,一切都是对象,在分布式环境中经常需要将Object从这一端网络或设备传递到另一端。这就需要有一种可以在两端传输数据的协议。Java序列化机制就是为了解决这个问题而产生。 如何序列化一个对象 一个对象能够序列化的前提是实现Serializable接口,Serializable接口没有方法,更像是个标记。有了这个标记的Class就能被序列化机制处理。 1.import java.io.Serializable; 2. 3.class TestSerial implements Serializable { 4. 5.public byte version = 100; 6. 7.public byte count = 0; 8. 9.} 然后我们写个程序将对象序列化并输出。ObjectOutputStream能把Object输出成Byte 流。我们将Byte流暂时存储到temp.out文件里。 1.public static void main(String args[]) throws IOException { 2. 3. FileOutputStream fos = new FileOutputStream("temp.out "); 4. 5. ObjectOutputStream oos = new ObjectOutputStream(fos); 6. 7. TestSerial ts = new TestSerial();

JAVA类与对象的创建

试验四 类和对象的创建 一.类的定义 类是组成Java程序的基本要素。类封装了一类对象的状态和方法。类用来定义对象的模板。 类的实现包括两部分:类声明和类体。基本格式为: 修饰符class类名[extends父类名]{ /*类体的内容*/ } 1.类声明 以下是一个类声明的例子。 class People成为类声明,People是类名。习惯上,类名的第一个字母大写,但这不是必须的。类的名字不能是Java中的关键字,要符合标识符规定,即类的名字可以由字母、下划线、数字或美元符号组成,并且第一个字母不能是数字。但给类命名时,最好遵守下列规则: (1)如果类名使用拉丁字母,那么名字的首写字母使用大写字母,如Hello、Time、People等。 (2)类名最好容易识别,当类名由几个“单词”复合而成时,每个单词的首写字母使用大写,如BeijingTi me、AmericanGame、HelloChina等。 2.类体 编写类的目的是为了描述一类事物共有的属性和功能,描述过程由类体来实现。类声明之后的一对大括号“{”、“}”以及它们之间的内容称为类体,大括号之间的内容称为类体的内容。 类体的内容由两部分构成:一部分是变量的定义,用来刻画属性;另一部分是方法的定义,用来刻画功能。 下面是一个类名为“Trapezia”的类,类体内容的变量定义部分定义了4个float类型变量:top、bottom、h igh和laderArea,方法定义部分定义了两个方法:“getArea”和“setHigh”。

二.对象 1.对象的创建 创建一个对象包括对象的声明和为对象分配内存两个步骤。 (1)对象的声明。 一般格式为: 类的名字对象名字; 如: 这里People是类的名字,zhubajie是我们声明的对象的名字。 (2)为声明的对象分配内存。 使用new运算符和类的构造方法为声明的对象分配内存,如果类中没有构造方法,系统会调用默认的构造方法(你一定还记得构造方法的名字必须和类名相同这一规定),如: 例1: 「注」如果类里定义了一个或多个构造方法,那么Java不提供默认的构造方法。 2.对象的使用 对象不仅可以改变自己变量的状态,而且还拥有了使用创建它的那个类中的方法的能力,对象通过使用这些方法可以产生一定的行为。 通过使用运算符“.”,对象可以实现对自己的变量访问和方法的调用。 例2:

Java技术详细介绍

Java技术详细介绍 Java的历史:微处理的革命最重要的也许就是它使全世界很快拥有3亿台个人计算机成为可能。个人计算机对个人以及对企业的生产管理方都产生了深刻的影响。 本文内容由天搜科技整理提供 Java程序由类组成,类则由方法构成。方法用来执行任务,并在完成任务时返回信息。用户可以编写类和方法,并由此建立一个Java程序,在编写过程中他们还应尽量充分利用Java类库中已存在的丰富的类和方法。类库就是Java API(Applications Programming Interface,应用程序接口).因此学习Java 语言实际上包括两个方面:一方面是学习用Java语言编写自己所需的类和方法,另一方面是学习如何利用Java类库中的类和方法。 Java核心技术有哪四个? 1.Java虚拟机 2.类装载器的体系结构 3.Java class文件 4.Java API 下面分别介绍Java四个核心技术的应用: Java虚拟机 Java虚拟机处于机器和编译程序之间,在任何平台上都提供给编译程序一个共同的接口。Java源程序经过编译器编译后变成字节码,字节码由虚拟机解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机器上的机器码,然后在特定的机器上运行,Java应用程序能够在运行时决定需要安装的类,并且将被不同的类装载器装载的类存放在不同的命名空间。 类装载器的体系结构 一个Java应用程序可以使用两种类装载器:"启动(bootstrap)"类装载器和用户定义的类装载器。启动类装载器(这是系统中唯一的)是Java虚拟机实现的一部分。启动类装载器通常使用某种默认方式从本地磁盘中装载类,包括Java API类(启动类装载器也被称为原始类装载器、系统类装载器或者默认类装载器)。

java序列化的作用

1、序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。 2、什么情况下需要序列化 a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候; b)当你想用套接字在网络上传送对象的时候; c)当你想通过RMI传输对象的时候; 3、当对一个对象实现序列化时,究竟发生了什么? 在没有序列化前,每个保存在堆(Heap)中的对象都有相应的状态(state),即实例变量(instance ariable)比如: java 代码 1.Foo myFoo = new Foo(); 2.myFoo .setWidth(37); 3.myFoo.setHeight(70); 当通过下面的代码序列化之后,MyFoo对象中的width和Height实例变量的值(3 7,70)都被保存到foo.ser文件中,这样以后又可以把它从文件中读出来,重新在堆中创建原来的对象。当然保存时候不仅仅是保存对象的实例变量的值,JVM还要保存一些小量信息,比如类的类型等以便恢复原来的对象。 java 代码 1.FileOutputStream fs = new FileOutputStream("foo.ser"); 2.ObjectOutputStream os = new ObjectOutputStream(fs); 3.os.writeObject(myFoo); 4、实现序列化(保存到一个文件)的步骤 a)Make a FileOutputStream

Java对象的序列化和反序列化实践

Java对象的序列化和反序列化实践 当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。 把Java对象转换为字节序列的过程称为对象的序列化。 把字节序列恢复为Java对象的过程称为对象的反序列化。 对象的序列化主要有两种用途: 1)把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中; 2)在网络上传送对象的字节序列。 一.JDK类库中的序列化API java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。 java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。、 只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以采用默认的序列化方式。 对象序列化包括如下步骤: 1)创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流; 2)通过对象输出流的writeObject()方法写对象。 对象反序列化的步骤如下: 1)创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;

《JAVA面向对象编程》([PDF] 孙卫琴著)

《JAVA面向对象编程》[PDF] 孙卫琴著 【目录】 第1章面向对象开发方法概述 1 1.1 结构化的软件开发方法简介3 1.2 面向对象的软件开发方法简介5 1.2.1 对象模型6 1.2.2 UML:可视化建模语言6 1.2.3 Rational Rose:可视化建模工具7 1.3 面向对象开发中的核心思想和概念7 1.3.1 问题领域、对象、属性、状态、行为、方法、实现7 1.3.2 类、类型9 1.3.3 消息、服务10 1.3.4 接口11 1.3.5 封装、透明12 1.3.6 抽象16 1.3.7 继承、扩展、覆盖17 1.3.8 组合19 1.3.9 多态、动态绑定22 1.4 UML语言简介24 1.4.1 用例图24 1.4.2 类框图25 1.4.3 时序图26 1.4.4 协作图27 1.4.5 状态转换图27 1.4.6 组件图28 1.4.7 部署图29 1.5 类之间的关系29 1.5.1 关联(Association)29 1.5.2 依赖(Dependency)31 1.5.3 聚集(Aggregation)31 1.5.4 泛化(Generalization)32 1.5.5 实现(Realization)32 1.5.6 区分依赖、关联和聚集关系33 1.6 实现Panel系统35 1.6.1 扩展Panel系统37 1.6.2 用配置文件进一步提高Panel系统的可维护性39 1.6.3 运行Panel系统40 1.7 小结41 1.8 思考题42 第2章第一个Java应用43 2.1 创建Java源文件43 2.1.1 Java源文件结构44

深入探讨、理解Java的CLASSPATH

深入探讨、理解Java的CLASSPATH 来源: 本站原创 从表面上看,Java的classpath(类路径)很简单,但一直以来它都是一个产生问题和混乱的根源。本文介绍classpath的基本知识、可能产生的问题,并提供了一个简单的classpath管理工具。 和Java类路径(classpath)打交道的过程中,开发者偶尔会遇到麻烦。这是因为,类装载器实际装入的是哪一个类有时并不显而易见,当应用程序的classpath 包含大量的类和目录时,情况尤其严重。本文将提供一个工具,它能够显示出被装入类文件的绝对路径名。 一、Classpath基础 Java虚拟机(JVM)借助类装载器装入应用程序使用的类,具体装入哪些类根据当时的需要决定。CLASSPATH环境变量告诉类装载器到哪里去寻找第三方提供的类和用户定义的类。另外,你也可以使用JVM命令行参数-classpath分别为应用程序指定类路径,在-classpath中指定的类路径覆盖CLASSPATH环境变量中指定的值。 类路径中的内容可以是:文件的目录(包含不在包里面的类),包的根目录(包含已打包的类),包含类的档案文件(比如.zip文件或者.jar文件)。在Unix家族的系统上,类路径的各个项目由冒号分隔,在MS Windows系统上,它们由分号分隔。 类装载器以委托层次的形式组织,每一个类装载器有一个父类装载器。当一个类装载器被要求装载某个类时,它在尝试自己寻找类之前会把请求先委托给它的父类装载器。系统类装载器,即由安装在系统上的JDK或JRE提供的默认类装载器,通过CLASSPATH环境变量或者-classpath这个JVM命令行参数装入第三方提供的类或者用户定义的类。系统类装载器委托扩展类装载器装入使用Java Extension机制的类。扩展类装载器委托自举类装载器(bootstrap class loader)装入核心JDK类。 你可以自己开发特殊的类装载器,定制JVM如何动态地装入类。例如,大多数Servlet引擎使用定制的类装载器,动态地装入那些在classpath指定的目录内发生变化的类。

相关文档
最新文档