June 6, 2020
Hot Topics:

Java Language Integrity & Security: Serializing Classes

  • By Matt Weisfeld
  • Send Email »
  • More Articles »

Compiling the Code

I used a Command Prompt to compile the code. On certain machines, it is called a DOS Shell; on others, it is called a Command Prompt. You can open a Command Prompt in the Programs->Accessories option area.

Type the following code at the command prompt to compile all three of the files. I created a batch file called make.bat to handle this so I don't have to keep typing in these lines of code. Thus, all I have to do is type out the word make at the C: prompt like this:

C:column31> make

This command will invoke the make.bat file and execute the following lines of code.

"C:Program FilesJavajdk1.5.0_06binjavac"
   -classpath . Employee.java
"C:Program FilesJavajdk1.5.0_06binjavac"
   -classpath . Client.java
"C:Program FilesJavajdk1.5.0_06binjavac"
   -classpath . Server.java

Figure 1 shows the screen shot of what happens when this batch file is executed and the Java files are compiled.

Click here for a larger image.

Figure 1: Compiling the Code

At this point, you now will have three class files: Employee.class, Server.class, and Client.class. Employee.class is the class that will be sent over the network; Client.class and Server.class represent the client and server applications respectively. These files are seen in Figure 2.

Click here for a larger image.

Figure 2: The application code

Starting the Server

In one of the DOS Shells, type the following line at the command prompt:

"C:Program FilesJavajdk1.5.0_06binjava" –classpath . Server

Figure 3 shows what happens in Command Prompt.

Click here for a larger image.

Figure 3: Starting the Server

If everything is working properly, the "Server Waiting" message is displayed. At this point, you can start the Client.

Starting the Client

In a separate DOS Shell, start the Client with the following line.

"C:Program FilesJavajdk1.5.0_06binjava" -classpath . Client

The result is shown in Figure 4.

Click here for a larger image.

Figure 4: Starting the Client

If all is well, you will see that the employeeNumber has been updated by the server. The original value of 150 was sent to the server by the client. The server then updated the employeeNumber and sent that value back to the client—which then prints it. You can put some specific identification in the print statements to provide further assurance.

With the circuit complete, the Server should exit cleanly, as shown in Figure 5.

Click here for a larger image.

Figure 5: Completing the System

Causing Trouble

Now that the framework for this example is in place, explore a situation that may cause some application integrity and security issues.

It is important to note that the both Client.java and Server.java use the same definition of the Employee class. The Client instantiates the actual Employee object:

Employee joe = new Employee(150);

Whereas the Server creates an Employee reference and uses this as a handle to the Employee object that comes off the network connection; see Diagram 2.

Diagram 2: Passing the Employee object

This represents one of the beauties of dynamically loading classes; the Server can accept a valid Employee object from any Client that chooses to send it one. The operative term here is valid. As you saw in the previous article, the Employee class definition can change without that update being reflected in the Employee class definition that the Server is using. In other words, what happens if the Client and Server both start off with the same Employee class definition but the Client decides to change the Employee class without broadcasting the change to the Server? See what happens.

Separating the Server

To illustrate this, you need to move the Server into a separate directory. The reason for this provides a good demonstration of how classes are dynamically loaded. First, change the Employee class by adding another attribute, the added attribute employeeName in Listing 4.

Listing 4: The Updated Employee Class

import java.io.*;
import java.util.*;

public class Employee implements Serializable {

private int employeeName;
private int employeeNumber; Employee(int num) { employeeNumber = num; } public int getEmployeeNumber() { return employeeNumber ; } public void setEmployeeNumber(int num) { employeeNumber = num; } }

Now, recompile the example; however, do not recompile the Server. This is simple to do by using the rem Command Prompt keyword. This keyword treats the line as a remark, or comment, and will not execute it.

"C:Program FilesJavajdk1.5.0_06binjavac"
   -classpath . Employee.java
"C:Program FilesJavajdk1.5.0_06binjavac"
   -classpath . Client.java
rem "C:Program FilesJavajdk1.5.0_06binjavac"
   -classpath . Server.java

Now, execute the complete system in the exact same way as you did earlier in the article. You should get the exact same results.

This may seem surprising because you did not recompile the Server to reflect the change in the Client. However, don't forget that the Employee class definition was recompiled and that the Server loads it dynamically—thus, the Server actually did pick up the new version. To really check what happens if the Client and Server have different versions of the Employee class, you need to separate the Server from the Client and make sure that they truly have different versions of the Employee class.

To accomplish this, you can simply create a new directory, call it Server, and place a copy of the original version of the Server and Employee class in this directory. This setup is shown in Figure 6. Note that the only files in this directory are the original version of the Employee class, the Server, and the batch file that starts the Server.

Click here for a larger image.

Figure 6: The Separate Server Directory

Now return to the directory that contains the entire application,


The Employee object and the Client include the updated code with the following line—this is absent in the code inside the new server directory.

private int employeeName;

Now, you can start up the Server application from the new directory as seen in Figure 7.

Click here for a larger image.

Figure 7: Starting the Original Server

While the Server waits, you now complete the process by starting up the Client with the updated code as seen in Figure 8. Note that the Client application now throws an exception.

Click here for a larger image.

Figure 8: Starting the Original Server

The Server also encounters a problem; in fact, it crashes. You get the message:

java.io.InvalidClassException: Employee; local class incompatible:
   stream classd
esc serialVersionUID = 8052846892556280666,
   local class serialVersionUID = 75684

Click here for a larger image.

Figure 9: The Server Crashes

This message is generated because the serialVersionUID of the classes do not match. The serialVersionUID is one of the measures used by the Java environment to keep rogue classes from getting inserted into systems.

Note: I will discuss the serialization of objects in great detail in a later article.

Page 2 of 3

This article was originally published on February 5, 2007

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date