Please clear my understanding why I am getting of value of company after deserialization. I know "Statics are implicitly transient, so we don't need to declare them as such."
class Employee implements Serializable {
String name;
static String company = "My Company";
public Employee(String name) {
this.name = name;
}
}
public class Test8 {
public static void main(String[] args) throws Exception {
Employee e = new Employee("John");
serializeObject(e);// assume serialize works fine
Employee e1 = deserializeObject(); // assume deserialize works fine
System.out.println(e1.name + " " + e1.company);
}
public static void serializeObject(Employee e) throws IOException {
FileOutputStream fos = new FileOutputStream("Test8.cert");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(e);
oos.flush();
oos.close();
}
public static Employee deserializeObject() throws IOException, ClassNotFoundException {
FileInputStream fis = new FileInputStream("Test8.cert");
ObjectInputStream oos = new ObjectInputStream(fis);
return (Employee) oos.readObject();
}
}
Value of static field company was set first time you used Employee class. In your case it would be in line:
Employee e = new Employee("John");
This value didn't change since it wasn't serialized and deserialized so it stayed the same, which means
System.out.println(e1.name + " " + e1.company);
prints John My Company.
But even if you remove lines
Employee e = new Employee("John");
serializeObject(e);
from your code, and invoke only
public static void main(String[] args) throws Exception {
Employee e1 = deserializeObject(); // assume deserialize works fine
System.out.println(e1.name + " " + e1.company);
}
Employee class will still be loaded inside deserializeObject (by oos.readObject() method) so its static fields will also be properly initialized to its default values.
Related
I am working on a school project that basically allows the user to create, edit and display students. I have a createStudent() that writes the info into the file using Scanner and ObjectOutputStream. The displayStudent() reads the data from the file using ObjectInputStream and displays it. The idea with editStudent() is to ask the user to enter the ID of the student they want to edit and then change the date and write it back to the file, what I have been trying to do is read the data from the file using ObjectInputStream and then assign that data into ArrayList or HashMap, I think I will be using ArrayList because HashMap is unordered. When I try to add the data from the file into ArrayList I get the following error:
java.io.EOFException at java.base/java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:3231) at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1663) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:519) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:477) at MidTermProject.editStudent(MidTermProject.java:194) at MidTermProject.main(MidTermProject.java:381)
Here is my code for editStudent():
public static void editStudent() throws IOException {
int editID;
String student;
ArrayList<String> studentEdit = new ArrayList<String>();
Scanner keyboard = new Scanner(System.in);
FileInputStream fstream = new FileInputStream("studentInfo.dat");
ObjectInputStream inputFile = new ObjectInputStream(fstream);
System.out.print("Enter the ID of the student you would like to edit: ");
editID = keyboard.nextInt();
try {
student = (String) inputFile.readObject();
studentEdit.add(student);
System.out.print(studentEdit);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
///Added create student method
public static void createStudent() throws IOException {
File file = new File("studentInfo.dat");
boolean append = file.exists();
Scanner keyboard = new Scanner(System.in);
try (
FileOutputStream fout = new FileOutputStream(file, append);
MidTermProject oout = new MidTermProject(fout, append);
) {
id = idGenerator.getAndIncrement();
String convertedId = Integer.toString(getId());
oout.writeObject(convertedId);
System.out.print("\nPlease enter your information bellow.\n" + "\nFull Name: ");
FullName = keyboard.nextLine();
oout.writeObject(FullName);
System.out.print("Address: ");
address = keyboard.nextLine();
oout.writeObject(address);
System.out.print("City: ");
city = keyboard.nextLine();
oout.writeObject(city);
System.out.print("State: ");
state = keyboard.nextLine();
oout.writeObject(state);
oout.close();
System.out.println("Done!\n");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Here is the class code for MidTermProject
public class MidTermProject extends ObjectOutputStream {
private boolean append;
private boolean initialized;
private DataOutputStream dout;
static AtomicInteger idGenerator = new AtomicInteger(0001);
static int id;
public static String FullName;
public static String address;
public static String city;
public static String state;
public static String className;
public static String instructor;
public static String department;
public static String classNumber;
public static String courseNumber;
public static String year;
public static String semester;
public static String grade;
public static String studentID;
public static String courseID;
public static String enrollmentID;
public static HashMap<String, Integer> map = new HashMap<>();
Scanner keyboard = new Scanner(System.in);
protected MidTermProject(boolean append) throws IOException, SecurityException {
super();
this.append = append;
this.initialized = true;
}
public MidTermProject(OutputStream out, boolean append) throws IOException {
super(out);
this.append = append;
this.initialized = true;
this.dout = new DataOutputStream(out);
this.writeStreamHeader();
}
#Override
protected void writeStreamHeader() throws IOException {
if (!this.initialized || this.append) return;
if (dout != null) {
dout.writeShort(STREAM_MAGIC);
dout.writeShort(STREAM_VERSION);
}
}
If think you are misusing serialization: whether Serialization is bad or good is another matter, but that should be something like that:
List<Student> students = ... ;
try (OuputStream os = Files.newOutputStream(Paths.get("out"));
ObjectOutputStream oos = new ObjectOutputStream(os)) {
oos.writeObject(students);
}
Reading it should be as simple as:
try (InputStream is = Files.newInputStream(Paths.get("out"));
ObjectInputStream iis = new ObjectInputStream(is)) {
List<Student> students = iis.readObject(students);
}
You must ensure that Student is Serializable and have only Serializable or transient fields:
class Student implements Serializable {
private static final long serialVersionUID = 1L;
private long id;
private String fullName;
private String address;
private transient String wontBeExported;
...
}
Notice that the fields are not static: serialization is about serializing an object and its fields. Static fields are not part of any instance.
You should also not have to extends the ObjectOutputStream class, or if you do, you must ensure that you read the object written by your implementation of ObjectOutputStream is symmetric with the ObjectInputStream you are using:
If you write an header, your ObjectInputStream must read said header.
If you write an object, your ObjectInputStream must read said object.
And the order is important: you can't read the object before the header is read.
You should also read the Java tutorial: https://docs.oracle.com/javase/tutorial/jndi/objects/serial.html
I need to serialize an Object in java. Currently I'm doing it by using this code, which does:
ObjectOutputStream.writeObject(obj);
Base64 encode the obj
And reversing the process.
It works fine for primitive types inside the class, such as long and int.
However, all String objects inside that object become null. I'd need them to be included as well. Is there any way to do that?
Edit: code I'm using
// Modified from source: https://stackoverflow.com/questions/134492/how-to-serialize-an-object-into-a-string
public static Object FromString( String s )
{
Object o = null;
try {
byte[] data = Base64.getDecoder().decode(s);
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(data));
o = ois.readObject();
ois.close();
}
catch(Exception e)
{
System.out.println(e);
}
return o;
}
// Modified from source: https://stackoverflow.com/questions/134492/how-to-serialize-an-object-into-a-string
public static String ToString( Serializable o )
{
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
}
catch(Exception e)
{
System.out.println(e);
}
return Base64.getEncoder().encodeToString(baos.toByteArray());
}
EDIT: Pojo
public class SignedTimestamp implements Serializable {
private Long obj;
private byte[] signature;
private String signatureAsAString;
}
Output on the other application (receiving the data and deserializing):
obj = 1494609033621;
signature = null;
signatureAsAString = null;
I have just tested your code, and it's working okay.
I've created a source named SignedTimeStamp.java:
import java.io.*;
public class SignedTimestamp implements Serializable {
private Long obj;
private byte[] signature;
private String signatureAsAString;
public SignedTimestamp(Long obj, byte[] signature, String signatureAsAString) {
this.obj = obj;
this.signature = signature;
this.signatureAsAString = signatureAsAString;
}
public Long getObj() {
return this.obj;
}
public byte[] getSignature() {
return this.signature;
}
public String getSignatureAsAString() {
return this.signatureAsAString;
}
}
And declared another called Serializables.java, containing your code:
import java.io.;
import java.util.;
public class Serializables {
public static Object FromString(String s) {
Object o = null;
try {
byte[] data = Base64.getDecoder().decode(s);
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(data));
o = ois.readObject();
ois.close();
}
catch(Exception e)
{
System.out.println(e);
}
return o;
}
// Modified from source: http://stackoverflow.com/questions/134492/how-to-serialize-an-object-into-a-string
public static String ToString( Serializable o ) {
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
}
catch(Exception e)
{
System.out.println(e);
}
return Base64.getEncoder().encodeToString(baos.toByteArray());
}
}
Then, I created one main class in Serialize.java:
public class Serialize {
public static void main(String[] args) throws Exception {
SignedTimestamp o = new SignedTimestamp(100L, new byte[]{ (byte) 128 }, "Hello, world!");
System.out.println(Serializables.ToString(o));
}
}
Which returned me this result:
sh-4.3$ java Serialize
rO0ABXNyAA9TaWduZWRUaW1lc3RhbXCGTHiJ+JenzgIAA0wAA29ianQAEExqYXZhL2xhbmcvTG9uZztbAAlzaWduYXR1cmV0AAJbQkwAEnNpZ25hdHVyZUFzQVN0cmluZ3QAEkxqYXZhL2xhbmcvU3RyaW5nO3hwc3IADmphdmEubGFuZy
5Mb25nO4vkkMyPI98CAAFKAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAAAAABkdXIAAltCrPMX+AYIVOACAAB4cAAAAAGAdAANSGVsbG8sIHdvcmxkIQ==
sh-4.3$
Then, I created another main class in Deserialize.java:
public class Deserialize {
public static void main(String[] args) throws Exception {
String serialized =
"rO0ABXNyAA9TaWduZWRUaW1lc3RhbXCGTHiJ+JenzgIAA0wAA29ianQAEExqYXZhL2xhbmcvTG9uZztbAAlzaWduYXR1cmV0AAJbQkwAEnNpZ25hdHVyZUFzQVN0cmluZ3QAEkxqYXZhL2xhbmcvU3RyaW5nO3hwc3IADmphdmEubGFuZy" +
"5Mb25nO4vkkMyPI98CAAFKAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAAAAABkdXIAAltCrPMX+AYIVOACAAB4cAAAAAGAdAANSGVsbG8sIHdvcmxkIQ==";
SignedTimestamp o = (SignedTimestamp) Serializables.FromString(serialized);
System.out.println(o.getObj());
System.out.println(o.getSignature());
System.out.println(o.getSignatureAsAString());
}
}
And it returns this:
sh-4.3$ java Deserialize
100
[B#6bc7c054
Hello, world!
sh-4.3$
So, all in all, the code seems to be working perfectly.
How did you test your code? Perhaps the mistake is there.
I dont see any problem in that code. Please post your code so that we will dig further.
tried from my end:
Encoded serialized version
rO0ABXNyAAhFbXBsb3llZTLR4JLRYAw9AgAESQAGbnVtYmVyTAAHYWRkcmVzc3QAEkxqYXZhL2xhbmcvU3RyaW5nO0wADWFkZHJlc3NPYmplY3R0AAlMQWRkcmVzcztMAARuYW1lcQB+AAF4cAAAAGV0ABlQaG9ra2EgS3VhbiwgQW1iZWh0YSBQZWVyc3IAB0FkZHJlc3MkcEtPHXHTqQIAAUwACGFkZHJMaW5lcQB+AAF4cHEAfgAEdAAJUmV5YW4gQWxp
Reconstituted object
Employee [name=Reyan Ali, address=Phokka Kuan, Ambehta Peer, number=101, addressObject=Address [addrLine=Phokka Kuan, Ambehta Peer]]
I have a 'Person' class where i stored data like name, surname etc. I make 5 object type Person, add them to ArrayList, and save this ArrayList to file. Next i'm loading from this file ArrayList and i have 5 person. Problem is when i want save again for example 10 object Person. When i'm loading ArrayList from file i'm getting only 5 person from first writing. If i repeat this still i will have load data from first writing to this file. How i can fix this ?
public class Data {
static List<Person> persons = new ArrayList<Person>();
public static void main(String[] args) throws IOException {
Data.savePersons(5);
Data.loadPersons();
/** Clean 'persons' array for TEST of load data */
persons.removeAll(persons);
System.out.println("\n-----------\nNext Round\n-----------\n");
Data.savePersons(10);
Data.loadPersons();
}
/** Save a couple of Person Object to file C:/data.ser */
public static void savePersons(int noOfPersonToSave) throws IOException {
FileOutputStream fout = null;
ObjectOutputStream oos = null;
/** Make 5 'Person' object and add them to ArrayList 'persons' for example */
for (int i = 0; i < noOfPersonToSave; i++) {
Person personTest = new Person("name" + i, "surname" + i, "email" +i, "1234567890" +i);
persons.add(personTest);
}
try {
fout = new FileOutputStream("C:\\data.ser", true);
oos = new ObjectOutputStream(fout);
oos.writeObject(persons);
System.out.println("Saving '" + persons.size() + "' Object to Array");
System.out.println("persons.size() = " + persons.size());
System.out.println("savePersons() = OK");
} catch (Exception ex) {
System.out.println("Saving ERROR: " + ex.getMessage());
} finally {
if (oos != null) {
oos.close();
}
}
}
/** Load previously saved a couple of Person Object in file C:/data.ser */
public static void loadPersons() throws IOException {
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream("C:\\data.ser");
ois = new ObjectInputStream(fis);
persons = (List<Person>) ois.readObject();
//persons.add(result);
System.out.println("-------------------------");
System.out.println("Loading '" + persons.size() + "' Object from Array");
System.out.println("persons.size() = " + persons.size());
System.out.println("loadPersons() = OK");
} catch (Exception e) {
System.out.println("-------------------------");
System.out.println("Loading ERROR: " + e.getMessage());
} finally {
if (ois != null) {
ois.close();
}
}
}}
class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String surname;
private String mail;
private String telephone;
public Person(String n, String s, String m, String t) {
name = n;
surname = s;
mail = m;
telephone = t;
}
public String getName() {
return name;
}
public String getSurname() {
return surname;
}
public String getMail() {
return mail;
}
public String getTelephone() {
return telephone;
}}
new FileOutputStream("C:\\data.ser", true)
You're passing true for the append parameter. So you're appending a list of 10 persons to the file, after the already existing list of 5 people. And since you only read one list, you read the first you wrote, which contains 5 persons.
Pass false instead of true.
I wanna make an ArrayList of Student and save it to a file for later use. I successfully wrote it but when I read it back to ArrayList, I have only one Object.
public class Student implements Serializable{
public String fname, lname, course;
int section;
private static final long serialVersionUID = 1L;
public static ArrayList<Student> students = getStudent();
public Student() {
}
public Student(String fname, String lname, String course, int section){
this.fname = fname;
this.lname = lname;
this.course = course;
this.section = section;
}
public static void addStudent(){
String fname = GetInput.getInput("Enter the First Name: ");
String lname = GetInput.getInput("Enter the Last Name: ");
String course = GetInput.getInput("Enter the Course: ");
String S_section = GetInput.getInput("Enter the section: ");
int section = Integer.parseInt(S_section);
Student student = new Student(fname, lname, course, section);
students.add(student);
System.out.println("Writing to file...");
try {
writeToFile(student);
} catch (FileNotFoundException ex) {
System.out.println(ex.getMessage());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
public static ArrayList<Student> getStudent(){
try{
FileInputStream fis = new FileInputStream("C:\\students.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
ArrayList<Student> students1 = (ArrayList<Student>) ois.readObject();
ois.close();
return students1;
} catch( ClassNotFoundException | IOException ex){
System.out.println(ex.getMessage());
return null;
}
}
public static void listStudent(ArrayList<Student> students){
System.out.println("View the Records in the Database:");
for(Student student: students){
System.out.println("Name: " + student.fname + " " + student.lname);
System.out.println("Course: " + student.course);
System.out.println("Section: " + student.section);
System.out.println();
}
}
static void writeToFile(Student student) throws FileNotFoundException, IOException{
String path = "C:\\students.ser";
FileOutputStream fos = new FileOutputStream(path, true);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(student);
oos.close();
System.out.println("New Record has been written!");
}
When I read file by calling getStudent() and print it out by listStudent() I have only one record of the file.
Please help me!
Much appreciate.
EDIT
I had tried writing an arraylist to file and read it into arraylist. I'll show you how I did that.
Firstly, I write arraylist to file:
public static ArrayList<Student> students = new ArrayList<>();
public static void addStudent(){
Student student = new Student(fname, lname, course, section);
students.add(student);
System.out.println("Writing to file...");
try {
writeToFile(students);
}catch...
}
static void writeToFile(ArrayList<Student> students) throws FileNotFoundException, IOException{
String path = "C:\\students.ser";
FileOutputStream fos = new FileOutputStream(path, true);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(students);
oos.close();
System.out.println("New Record has been written!");
And then I read student file:
public static ArrayList<Student> getStudent(){
try{
FileInputStream fis = new FileInputStream("C:\\students.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
ArrayList<Student> students1 = (ArrayList<Student>) ois.readObject();
ois.close();
return students1;
} catch( ClassNotFoundException | IOException ex){
System.out.println(ex.getMessage());
return null;
}
}
I can see that in the file I have many objects as the file size keep growing. But I only one object after read it, which is my very first object I wrote to file.
I would suggest you update your Serialization code for your Student class (because you're not Serializing your static students) as follows -
// This controls how Student(s) will be written.
private void writeObject(ObjectOutputStream oos)
throws IOException {
oos.defaultWriteObject();
// How many students we're tracking.
oos.writeInt(students.size());
for (Student student : students) {
oos.writeObject(student);
}
System.out.println("session serialized");
}
// Control how we read in Student(s).
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
ois.defaultReadObject();
// how many Students to read.
int size = ois.readInt();
for (int i = 0; i < size; i++) {
Student s = (Student) ois.readObject();
students.add(s);
}
System.out.println("session deserialized");
}
You state in comment:
Thanks for your comment. I noticed that, however I appended the new object to the old file, so technically I have bunch of objects in my file. FileOutputStream fos = new FileOutputStream(path, true);
While this technically does append to the end of a file, and works great with text files, I really don't think that this will work or work well with serialization. I would guess that to append with serialization, you'd first have to read all the objects in from the file, and then write without appending all of them via the serialization mechanism. I would re-write your input and output code if I were you.
Edit
I fear that you've got too much disparate stuff all crammed into one single class, making for a messy and hard to debug program. Some general recommendations to help clean up this assignment:
First create a class called Student -- you've done this -- but make it a pure Student class with private first name, last name, section and course fields, getters and setters for those fields (you need these), appropriate constructors (I think you've got this).
Give it a decent public String toString() method that returns a String that holds the values of the object's fields.
Get everything else out of Student, all the static methods, all the ArrayLists, any code for writing to or reading from files.
Create another class, say called StudentCollection
Give it a private non-static ArrayList<Student> field, say called students.
Give it an addStudent(Student student) method that allows outside classes to add Student objects to this class.
Give it a public String toString() method that returns the list's toString(), i.e., return students.toString();.
Give it a public void readFromFile(File file) method that uses serialization to read an ArrayList<Student> from a File.
Give it a public void writeToFile(File file) method that uses serialization to write an ArrayList<Student> to a File.
Finally, create a TestStudent class that has only one method, a public static void main method.
In main, create a StudentCollection object.
Fill it with Students using your addStudent(...) method.
Create a File object and call writeToFile(...) passing in your File.
Then test reading from the same file...
For example, the main method could look almost like the code below. Note though that in my test case to prove that this works, I created a simplified Student class, one that only took 2 parameters, for first and last names. Your code obviously will take more parameters.
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class StudentTest {
private static final String DATA_FILE_PATH = "myFile.dat";
public static void main(String[] args) {
Student[] students = {new Student("John", "Smith"),
new Student("Mike", "Barnes"),
new Student("Mickey", "Mouse"),
new Student("Donald", "Duck")};
// create our collection object
StudentCollection studentColl1 = new StudentCollection();
// print out that it currently is empty
System.out.println("studentColl1: " + studentColl1);
// Add Student objects to it
for (Student student : students) {
studentColl1.addStudent(student);
}
// show that it is now full
System.out.println("studentColl1: " + studentColl1);
// create a file
File myFile = new File(DATA_FILE_PATH);
// write out our collection to file on disk
studentColl1.writeToFile(myFile);
// create another collection object
StudentCollection studentColl2 = new StudentCollection();
// show that it is empty
System.out.println("studentColl2: " + studentColl2);
// read the list back into the new StudentCollection object
File myFile2 = new File(DATA_FILE_PATH);
studentColl2.readFromFile(myFile2);
// add a few more Student's:
studentColl2.addStudent(new Student("Stack", "Overflow"));
studentColl2.addStudent(new Student("Donald", "Trump"));
// show the result
System.out.println("studentColl2: " + studentColl2);
}
}
You're writing a single Student object:
oos.writeObject(student);
But are trying to get an ArrayList:
ArrayList<Student> students1 = (ArrayList<Student>) ois.readObject();
I am reading Thinking in Java 4th Edition.
There described a strange workaround for serialization of transient fields:
import java.io.*;
public class SerializationTest implements Serializable {
private String firstData;
//transient field, shouldn't be serialized.
transient private String secondData;
public SerializationTest(String firstData, String test2) {
this.firstData = firstData;
this.secondData = test2;
}
/**
* Private method, same signature as in Serializable interface
*
* #param stream
* #throws IOException
*/
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeObject(secondData);
}
/**
* Private method, same signature as in Serializable interface
*
* #param stream
* #throws IOException
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
secondData = (String) stream.readObject();
}
#Override
public String toString() {
return "SerializationTest{" +
"firstData='" + firstData + '\'' +
", secondData='" + secondData + '\'' +
'}';
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream("object.out");
oos = new ObjectOutputStream(fos);
SerializationTest sTest = new SerializationTest("First Data", "Second data");
oos.writeObject(sTest);
} finally {
oos.close();
fos.close();
}
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream("object.out");
ois = new ObjectInputStream(fis);
SerializationTest sTest = (SerializationTest) ois.readObject();
System.out.println(sTest);
} finally {
ois.close();
fis.close();
}
//Output:
//SerializationTest{firstData='First Data', secondData='Second data'}
}
}
As you can see, there are implemented private methods writeObject and readObject.
The questions are:
For what ObjectOutputStream and ObjectInputStream are using Reflection for accessing private methods ?
How many back doors like this are included in the Java ?
Backdoor? It's always been in the spec. It is the only way to implement non-default serialization of an object.
Non-default serialization puts you in the serialization driver's seat. You can write whatever to the output stream and as long as you can read it back and construct your object on the other end of the stream, you'll be ok.
The fact that this person decided to serialize transient fields is just not the issue, the point is that you can do whatever you want if you are implementing your own serialization scheme.
Erm, it isn't a "backdoor" ... you implemented a custom serialization that output the transient fields to the output stream after calling the default serialization which ignored them.
The Serializable interface is marker interface. So its like a tag to explain the java compiler. There are other marker interfaces like Clonable, etc. See here for more.
However now a days #annotations are used more.