Serialization and Deserialization in Java Part: 2

TARA RAM GOYAL
4 min readApr 18, 2023

--

In this section, I will describe how we may keep our sensitive data safe during the serialization and deserialization operations.

Serialization & Deserialization in Java

This is the second part of our Java Serialization and Deserialization series. I strongly advise you to read my blog, Serialization and Deserialization in Java Part: 1, for a better understanding. In this section, I’ll explain how we can keep our sensitive data, such as passwords, account numbers, and so on, safe during the serialiation and deserialization processes, because these fields are too sensitive, and if we don’t care about them, we’ll pay a price.

In Java we can achieve this issue by using transient modifier/keyword.

transient is a modifier in java and which is application only for at variable but not for methods and classes. At the time of serialization if we doesn't want to save the value of a particular variable to meet security constraint then we must have declared that variable as transient modifiers.

While performing serialization JVM simply ignore the original value of transient variable and save default value in the file. Hence, transient means not to serialize.

transient vs static

static variable is not part of object states and hence it won’t participant in serialization due to this declaring static variable as transient their is no use.

final vs transient

final variable will be participant in serialization directly by value (as you know all the final variable is replaced with their value at compile-time) hence, declaring a final variable as transient their is no impact here

I’m adding a code snippet if we are not using the transient modifier —

class User implements Serializable {

int userId;
String name;
String password;

public User(int userId, String name, String password) {
this.userId = userId;
this.name = name;
this.password = password;
}
}

public class SerializationDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {

User user = new User(1456, "Andy", "Andy@56");
System.out.println("Output before serialization");
System.out.println("User id: " + user.userId + "\nUser name: " + user.name + "\nUser password: " + user.password);
FileOutputStream fileOutputStream = new FileOutputStream("user.ser");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(user);

FileInputStream fileInputStream = new FileInputStream("user.ser");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);

User existingUser = (User) objectInputStream.readObject();
System.out.println("\nOutput after serialization & deserialization");
System.out.println("User id: " + existingUser.userId + "\nUser name: " + existingUser.name + "\nUser password: " + existingUser.password);

}
}

/**
* Output before serialization
* User id: 1456
* User name: Andy
* User password: Andy@56
*
* Output after serialization & deserialization
* User id: 1456
*
Internal representation of serialization & deserialization

In the above example, we are not using a transient modifier, and while we persist or transmit the states of an object, we also persist or transmit sensitive data (the user’s password), which is harmful and violates a security constraint.

Now, I’m adding a code snippet if we are using the transient modifier —

class User implements Serializable {

int userId;
String name;
transient String password;

public User(int userId, String name, String password) {
this.userId = userId;
this.name = name;
this.password = password;
}
}

public class SerializationDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {

User user = new User(1456, "Andy", "Andy@56");
System.out.println("Output before serialization");
System.out.println("User id: " + user.userId + "\nUser name: " + user.name + "\nUser password: " + user.password);
FileOutputStream fileOutputStream = new FileOutputStream("user.ser");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(user);

FileInputStream fileInputStream = new FileInputStream("user.ser");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);

User existingUser = (User) objectInputStream.readObject();
System.out.println("\nOutput after serialization & deserialization");
System.out.println("User id: " + existingUser.userId + "\nUser name: " + existingUser.name + "\nUser password: " + existingUser.password);

}
}


/**
* Output before serialization
* User id: 1456
* User name: Andy
* User password: Andy@56
*
* Output after serialization & deserialization
* User id: 1456
* User name: Andy
* User password: null
**/
Internal representation of serialization & deserialization

In the above example, we are using the transient modifier, and while we persist or transmit states of an object, JVM simply ignores the original value of the password field and assigns the default value (for a String, the default value is null). So this is not harmful or violating a security constraint.

I’ll give you an example with all of the scenarios where using a transient modifier is beneficial: —

In conclusion, if any fields present in an object contain sensitive data, then good programming practice requires that you use a transient modifier for them.

In the upcoming my post I’ll be explain about how we can serialize any no of object and how’s deserialize.

--

--