私はJavaアプリケーションを作成し、そのアプリケーションの2つのインスタンスを実行して、変更があるたびにソケットを介してそれらの属性の一部を同期する必要があります。これらの変更を伝えるために、Serializable
オブジェクトは、識別子にread / writeUTF()を使用するObjectStreams(入力および出力)を使用し、read / writeObject()およびflush()を使用して、ソケットを通じて送信されます。アプリはまったく同じ.jarであり、異なるポートやIPを使用するなどのいくつかの変更を加えて(必要に応じて)2回実行します。
一部のクラスのオブジェクト(例Notification
:)は問題なく送受信されましたが、別のクラス(RegisteredUsers
)のオブジェクトは正しく送信(または受信)されていません。したがって、2つのアプリ間でオブジェクトを送信するためにいくつかのテストを実行したところ、オブジェクトが送信されていてnullではないことがわかりました。属性(a HashMap<String,User>
)も送信されていて、nullではありませんが、常に空です。
だから私はそれを問題が正確に何であるかにスケールダウンすることにしました:ストリームを介してオブジェクトを書き、同じ.jarの異なるプロセスでそれを読み込もうとしています、そしてほとんどのクラスでそれはうまくいくようですが、それは1つではありません。
オブジェクトが同じプロセスの実行中に書き込まれて読み取られた場合は機能しますが、このオブジェクトが同じアプリの別のインスタンスで読み取られた場合は、このシリアル化プロセスについて私が見逃している、または理解できないものがあるようです。同じ作成プロセスで通知にHashMapを追加しましたが、それでも機能しますが、実際には取得できません。何が欠けていますか?
大きなアプリからいくつかのコードを取得し、テストしたい場合は基本的な問題に切り詰めました。エラーを再現するには、Main1を実行します。Main1を実行すると、それぞれにオブジェクトが永続化された2つのファイル(1つはNotificationオブジェクト、もう1つはRegisteredUsersオブジェクト)が作成され、それらの情報が表示されます。次にMain2がファイルからファイルを読み取り、それらの情報を示し、問題を印刷する必要があります。つまり、reg3のHashMapは空なので、どちらのユーザーも登録されていません。
メイン1
public class Main1 {
public static void main(String[] args) {
String regFile = "registry.txt";
String notificationFile = "notification.txt";
Persistence pers = new Persistence();
RegisteredUsers reg1 = new RegisteredUsers();
RegisteredUsers reg2 = new RegisteredUsers();
reg1.register("Name1", "127.0.0.1");
reg1.register("Name2", "127.0.0.1");
try {
pers.writeReg(reg1, regFile);
} catch (IOException e) {
System.out.println("Error writing registry.");
}
try {
reg2 = pers.readReg(regFile);
} catch (IOException e) {
System.out.println("Error reading registry.");
}
System.out.println("Original registry: ");
System.out.println(reg1.isRegistered("Name1") + " " + reg1.isRegistered("Name2"));
System.out.println("Registry read from file: ");
System.out.println(reg2.isRegistered("Name1") + " " + reg2.isRegistered("Name2"));
Notification noti1 = new Notification("Name", "127.0.0.1");
Notification noti2 = new Notification(); //not necesary but it's the way it's done in the bigger app.
try {
pers.writeNotif(noti1, notificationFile);
} catch (IOException e) {
System.out.println("Error writing notification.");
}
try {
noti2 = pers.readNotif(notificationFile);
} catch (IOException e) {
System.out.println("Error reading notification.");
}
System.out.println("Original notification: ");
System.out.println(noti1.getAttributes().get(0) + " " + noti1.getAttributes().get(1));
System.out.println(noti1.getMap());
System.out.println("Notification read from file: ");
System.out.println(noti2.getAttributes().get(0) + " " + noti2.getAttributes().get(1));
System.out.println(noti2.getMap());
}
}
メイン2
public class Main2 {
public static void main(String[] args) {
String regFile = "registry.txt";
String notificationFile = "notification.txt";
Persistence pers = new Persistence();
RegisteredUsers reg3 = new RegisteredUsers();
try {
reg3 = pers.readReg(regFile);
} catch (IOException e) {
System.out.println("Error reading registry.");
}
if (reg3 == null) {
System.out.println("reg3 is null");
}
if (reg3.getMap() == null)
System.out.println("reg3 has a null map");
if (reg3.getMap().isEmpty())
System.out.println("reg3 has an empty map");
System.out.println("Registry read from file on another process: ");
System.out.println(reg3.isRegistered("Name1") + " " + reg3.isRegistered("Name2"));
Notification noti3 = new Notification(); //not necesary but it's the way it's done in the bigger app.
try {
noti3 = pers.readNotif(notificationFile);
} catch (IOException e) {
System.out.println("Error reading notification.");
}
System.out.println("Notification read from file on another process: ");
System.out.println(noti3.getAttributes().get(0) + " " + noti3.getAttributes().get(1));
System.out.println(noti3.getMap());
}
}
ファイル内のオブジェクトを永続化するクラス:
public class Persistence {
public void writeReg(RegisteredUsers regus, String file) throws IOException {
try(FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);) {
oos.writeObject(regus);
oos.flush();
}
}
public RegisteredUsers readReg(String file) throws IOException {
RegisteredUsers regus = null;
try(FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);) {
regus = (RegisteredUsers) ois.readObject();
} catch (ClassNotFoundException e) {
System.out.println("Wrong class.");
}
return regus;
}
public void writeNotif(Notification regus, String file) throws IOException {
try(FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);) {
oos.writeObject(regus);
oos.flush();
}
}
public Notification readNotif(String file) throws IOException {
Notification notif = null;
try(FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);) {
notif = (Notification) ois.readObject();
} catch (ClassNotFoundException e) {
System.out.println("Wrong class.");
}
return notif;
}
}
登録ユーザー
public class RegisteredUsers implements Serializable {
private static HashMap<String, User> users;
public RegisteredUsers() {
users = new HashMap<String, User>();
}
public HashMap<String, User> getMap() {
return users;
}
public boolean isRegistered(String name) {
User us = users.get(name);
return us != null;
}
public void register(String name, String ip) {
users.put(name, new User(name, ip, false));
}
}
通知
public class Notification implements Serializable {
private ArrayList<String> attributes;
private HashMap<String, User> map = new HashMap<>();
public Notification() {
}
public Notification(String name, String ip) {
attributes = new ArrayList<String>();
attributes.add(0, name);
attributes.add(1, ip);
map.put(ip, new User(name, ip, false));
}
public ArrayList<String> getAttributes() {
return attributes;
}
public HashMap<String, User> getMap() {
return map;
}
}
ユーザー
public class User implements Serializable {
private String name;
private String ip;
private boolean connection_state;
public User(String name, String ip, boolean connection_state) {
this.name = name;
this.ip = ip;
this.connection_state = connection_state;
}
}
Javaのstatic
フィールドは暗黙的transient
にあり、一時フィールドはシリアル化されません。
あなたは、変更した場合RegisterdUsers
に
public class RegisteredUsers implements Serializable {
private HashMap<String, User> users; // static modifier is removed
...
}
シリアル化は機能します。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加