.class
のファイルはあるが のファイルPerson
がないという前提で操作しています。(おそらく、別のプロジェクトからの依存関係ですか?).class
Address
Person
Person
(フィールドが一時的であっても)シリアル化できない理由Address
は、シリアル化 API が Java リフレクション API を使用するためです。JVM はすべての依存関係をロードせずにクラスをロードしますが、リフレクション API はそれほど寛容ではありません。
リフレクション API を初めて使用して特定のクラスのフィールド情報を取得すると、そのクラスのすべてのフィールドの情報が取得され、キャッシュされます。これを行うには、クラス内のすべてのフィールドの型を解決する必要があるため、すべてのフィールドのクラス ファイルをロードしようとします。(これは Java ソース コードで確認できます: ObjectOutputStream
usesObjectStreamClass
を呼び出します。これは、クラスのすべてのフィールド定義を解決してキャッシュするClass.getDeclaredField
プライベート メソッドを呼び出します。)privateGetDeclaredFields
回避策として、コードで type のオブジェクトを実際に使用しない場合はAddress
、正しいパッケージに空のAddress
クラスを作成し、コンパイルして、クラス パスに追加するだけです。
public class Address { }
クラス定義Person
なしでは実行時に使用できないと考える人のために、次の 3 つのクラスは OP が何について話しているかを示しています。Address
Person.java
import java.io.Serializable;
public class Person implements Serializable {
private String name;
private transient Address address;
public Person(String name) { this.name = name; }
public Address getAddress() { return address; }
public String getName() { return name; }
}
アドレス.java
public class Address {
private String address;
public String getAddress() { return address; }
}
テスト.java
import java.io.FileOutputStream;
import java.io.ObjectOuputStream;
public class Test {
public static void main(String...args) throws Exception {
Person person = new Person("John Doe");
System.out.println("Person successfully instantiated with name " + person.getName());
// now attempt to serialize
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("person.out"));
out.writeObject(person); // NoClassDefFoundError thrown here if Address.class doesn't exist
out.close();
}
}
次に、コンパイルTest.java
、削除Address.class
、および実行しますTest
。
$ javac Test.java
$ rm Address.class
$ java Test
Person successfully instantiated with name John Doe
Exception in thread "main" java.lang.NoClassDefFoundError: LAddress;
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2308)
at java.lang.Class.getDeclaredField(Class.java:1897)
at java.io.ObjectStreamClass.getDeclaredSUID(ObjectStreamClass.java:1624)
at java.io.ObjectStreamClass.access$700(ObjectStreamClass.java:69)
at java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:442)
at java.security.AccessController.doPrivileged(Native Method)
at java.io.ObjectStreamClass.<init>(ObjectStreamClass.java:430)
at java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:327)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1130)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
at Test.main(Test.java:10)
Caused by: java.lang.ClassNotFoundException: Address
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
... 12 more