You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MPI-JAVA中自定义类对象的发送与接收问题求助

MPI序列化对象收发失败的问题排查与修复

核心问题分析

  • 二进制数据转String导致数据丢失:序列化后的字节流是二进制格式,直接调用baos.toString()会将其按默认字符编码(如UTF-8)转换为字符串,但很多二进制字节无法被正确编码为有效字符,转换过程中会丢失或损坏数据,导致反序列化时无法重构对象。
  • 错误使用MPI.CHAR类型发送:MPI的CHAR类型对应字符数据,而序列化对象是字节流,应该使用MPI.BYTE类型发送原始字节数组。
  • 接收端硬编码数组大小:固定115长度的接收数组,若实际序列化后的字节数超过或不足这个值,都会导致接收数据不完整或包含无效填充,反序列化失败。

修复后的代码实现

步骤1:确保ObjectProva类正确实现Serializable

首先要确认ObjectProva类已经实现Serializable接口,否则序列化本身就会失败:

import java.io.Serializable;

public class ObjectProva implements Serializable {
    private int id;
    private String name;

    public ObjectProva(int id, String name) {
        this.id = id;
        this.name = name;
    }

    // 可选:添加getter方法用于验证结果
    public int getId() { return id; }
    public String getName() { return name; }
}

步骤2:修正MPI收发逻辑,直接处理字节数组

ObjectProva obj = new ObjectProva(1,"test");
int rank = MPI.COMM_WORLD.Rank();

if (rank == 0) {
    // 序列化对象到字节数组
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
        oos.writeObject(obj);
        oos.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }
    byte[] serializedBytes = baos.toByteArray();
    
    // 先发送字节数组的长度,让接收端知道要接收多少数据
    MPI.COMM_WORLD.send(new int[]{serializedBytes.length}, 1, MPI.INT, 1, 0);
    // 发送序列化后的字节数组
    MPI.COMM_WORLD.send(serializedBytes, serializedBytes.length, MPI.BYTE, 1, 1);
} else {
    ObjectProva ob = null;
    // 先接收字节数组的长度
    int[] lengthArr = new int[1];
    MPI.COMM_WORLD.recv(lengthArr, 1, MPI.INT, 0, 0);
    int dataLength = lengthArr[0];
    
    // 根据长度创建接收数组,接收序列化字节
    byte[] receivedBytes = new byte[dataLength];
    MPI.COMM_WORLD.recv(receivedBytes, dataLength, MPI.BYTE, 0, 1);
    
    // 反序列化对象
    try (ByteArrayInputStream bis = new ByteArrayInputStream(receivedBytes);
         ObjectInputStream ois = new ObjectInputStream(bis)) {
        ob = (ObjectProva) ois.readObject();
        // 验证结果
        System.out.println("Received object: id=" + ob.getId() + ", name=" + ob.getName());
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    }
}

关键改进点说明

  • 直接传输字节数组:跳过String和char数组的转换,直接使用MPI.BYTE类型发送序列化后的原始字节,避免编码丢失。
  • 先发送数据长度:接收端先获取要接收的字节数,再创建对应大小的数组,确保接收完整的数据。
  • 使用try-with-resources:自动关闭流资源,避免资源泄漏。

内容的提问来源于stack exchange,提问作者StuckedJava

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 11:24:23