首页 > 编程语言 >Java安全基础之Java序列化与反序列化

Java安全基础之Java序列化与反序列化

时间:2024-04-21 13:11:31浏览次数:20  
标签:Java 字节 ObjectInputStream 对象 安全 new 序列化 ObjectOutputStream

目录

Java 的序列化(Serialization)是指将对象转换为字节序列的过程,而反序列化(Deserialization)则是将字节序列转换回对象的过程。

序列化和反序列化通常用于在网络上传输对象或者将对象持久化到文件系统中。

Java 提供了 java.io.Serializable 接口来支持对象的序列化和反序列化。如果一个类实现了 Serializable 接口,那么该类的对象就可以被序列化和反序列化。

ObjectInputStream 和 ObjectOutputStream

ObjectInputStream 和 ObjectOutputStream 是 Java 中用于序列化和反序列化对象的类,它们提供了将对象转换为字节流并将字节流转换回对象的功能。

  • ObjectOutputStream:用于将对象序列化为字节流,依赖于 writeObject() 方法。

  • ObjectInputStream:用于从字节流反序列化对象,依赖于 readObject() 方法。

try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.ser"))) {
    // 写入对象到文件
    out.writeObject(myObject);
} catch (IOException e) {
    e.printStackTrace();
}

try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.ser"))) {
    // 从文件中读取对象
    MyObject myObject = (MyObject) in.readObject();
} catch (IOException | ClassNotFoundException e) {
    e.printStackTrace();
}

java.io.Serializable

Serializable 这个接口本身并不包含任何方法,它只是一个空接口,其作用是告诉 Java 编译器,这个类的对象可以被序列化成字节流,也可以从字节流中反序列化成对象。

使用文件流进行序列化: 将对象序列化到文件中,使用 FileOutputStream 和 FileInputStream 进行读写操作。

import java.io.*;

public class SerializationExample {
    public static void main(String[] args) {
        try {
            String obj = "serialization example";

            // 序列化对象到文件
            FileOutputStream fos = new FileOutputStream("object.ser");
            ObjectOutputStream os = new ObjectOutputStream(fos);
            os.writeObject(obj);
            os.close();

            //反序列化对象到文件
            FileInputStream fis = new FileInputStream("object.ser");
            ObjectInputStream ois = new ObjectInputStream(fis);
            String dobj = (String)ois.readObject();
            System.out.print(dobj);
            ois.close();

        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}

使用字节数组进行序列化: 还可以使用 ByteArrayOutputStream 和 ByteArrayInputStream 将对象序列化到字节数组中。

import java.io.*;

public class SerializationExample {
    public static void main(String[] args) {
        try {
            String obj = "serialization example";

            // 序列化对象到字节数组
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ObjectOutputStream os = new ObjectOutputStream(byteArrayOutputStream);
            os.writeObject(obj);
            os.close();

            // 从字节数组反序列化对象
            byte[] byteArray = byteArrayOutputStream.toByteArray();
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);
            ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream);
            String dobj = (String) ois.readObject();
            System.out.print(dobj);
            ois.close();

        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}

除了可以将对象序列化到文件流和字节数组,还可以将对象序列化到网络流、缓存流等。除了 Java 原生的序列化方式外,还有一些第三方库可以进行对象的序列化,例如 JSON 序列化或者 XML 序列。

自定义序列化和反序列化

在 Java 中,可以通过实现 writeObject() 和 readObject() 方法来自定义序列化和反序列化过程,可以更灵活地控制对象在序列化和反序列化过程中的行为。

  • 自定义序列化:private void writeObject(ObjectOutputStream oos)

  • 自定义反序列化:private void readObject(ObjectInputStream ois)

例如:Person 类实现了 Serializable 接口

class Person implements Serializable {
    private String name;
    private transient int age; // transient 表示该字段不参与序列化

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 自定义序列化方法
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject(); // 默认序列化其他字段
        // 手动序列化 age 字段
        out.writeInt(age);
    }

    // 自定义反序列化方法
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject(); // 默认反序列化其他字段
        // 手动反序列化 age 字段
        age = in.readInt();
    }
}

过在待序列化或反序列化的类中定义 readObject 和 writeObject 方法,就来实现自定义的序列化和反序列化操作。

标签:Java,字节,ObjectInputStream,对象,安全,new,序列化,ObjectOutputStream
From: https://www.cnblogs.com/smileleooo/p/18148815

相关文章

  • Java基础
    基础语法注释、标识符、关键字注释:单行、多行、文档注释///*注释*//***/标识符字母$_关键字数据类型强类型语言:先定义后使用弱类型语言基本类型(primitive)数字类型整数类型byteshortintlong浮点类型floatdouble......
  • 三次答题判题程序练习让你入门Java。
    (1)前言本阶段三次题目集涵盖了从基础编程概念到较复杂算法设计等多个知识点。题量适中,难度呈梯度上升,从简单的数据结构与算法实现到复杂的问题求解,逐步挑战学生的编程能力。第一次题目集主要考察基本语法、数据类型和简单的控制结构;第二次题目集则增加了数组、链表等数据结构的应......
  • Java设计模式-责任链模式,应用接口多个参数验证,订单多个费用的计算
    Java设计模式-责任链模式,应用接口多个参数验证,订单多个费用的计算1.定义请求和返回对象的上下文对象packagecom.example.core.mydemo.java.filter;importjava.time.LocalDateTime;publicclassOrderReqContext{/***租客会员号*/StringmemNo;......
  • Java面试题:请谈谈对ThreadLocal的理解?
    ThreadLocal是一种特殊的变量存储机制,它提供了一种方式,可以在每个线程中保存数据,而不会受到其他线程的影响。这种机制在多线程编程中非常有用,因为它允许每个线程拥有自己的数据副本,从而避免了数据竞争和线程之间的干扰,以空间换时间。在Java中,ThreadLocal的实现主要涉及到三个类:Th......
  • [转帖]十年拉锯战终结束,Google 赢得 Java API 版权诉讼
    https://www.oschina.net/news/136073/googles-wins-lawsuit Google和Oracle(甲骨文)在法庭上就Android操作系统中Java编程语言的使用问题争吵了十年。美国最高法院在周一以6比2的投票结果裁定,Google对Java代码的使用被归为"合理使用",没有违反联邦版权法......
  • [转帖]Oracle 败了、谷歌赢了:Java API 版权案最终裁决
    https://zhuanlan.zhihu.com/p/362496136 周一,最高法院在Oracle围绕移动操作系统Android中所用软件的一起旷日持久的版权诉讼中判谷歌胜诉。法院的判决为6比2。大法官AmyConeyBarrett没有参与此案。该案涉及谷歌用于构建Android的12000行代码,这些代码是从SunMicrosy......
  • Solon Java 应用开发框架 v2.7.5 发布
    JavaSolon是什么框架?Java“新的”应用开发框架。从零开始构建(非java-ee架构),有灵活的接口规范与开放生态。追求:更快、更小、更简单提倡:克制、简洁、高效、开放、生态有什么特点?更高的计算性价比:并发高2~3倍;内存省50%更快的开发效率:内核小,入门快;调试重启快5......
  • 最新Java面试题带答案【2024中级】
    互联网大厂面试题1:阿里巴巴Java面试题2:阿里云Java面试题-实习生岗3:腾讯Java面试题-高级4:字节跳动Java面试题5:字节跳动Java面试题-大数据方向6:百度Java面试题7:蚂蚁金服Java面试题-中级8:蚂蚁金服Java面试题-高级9:京东Java面试题-中级10:拼多多Java面试题-电商部11:商汤科技......
  • 在Linux中,如何在Linux中实现虚拟化的安全最佳实践?
    在Linux环境中实施虚拟化时,确保安全的最佳实践涵盖了多个层面,包括主机安全、虚拟机安全、网络隔离、数据保护以及安全管理等方面。以下是针对Linux虚拟化安全的一系列重要措施:1.主机安全保持主机操作系统更新:定期更新主机系统及其组件(如内核、虚拟化软件等)以修复已知漏洞。最......
  • java 异步任务,定时任务,邮件发送
    java异步任务,定时任务,邮件异步任务异步方法注解:@Async主程序开启异步注解功能:@EnableAsync定时任务开启定时功能的注解在main:@EnableSchedulingTaskScheduler:任务调用者TaskExecutor:任务执行者@EnableScheduling开启定时功能的注解@Scheduled固定......