Serialization
Serialization enables the state of objects in a Java program to be captured and written out to a byte stream \[ [Sun 04b|AA. Bibliography#Sun 04b]\]. This allows for the object state to be preserved so that it can be reinstated in the future (by deserialization). Serialization also allows for Java method calls to be transmitted over a network for Remote Method Invocation (RMI) wherein objects are marshalled (serialized), exchanged between distributed virtual machines, and unmarshalled (deserialized). An object (called {{someObject}} in the following example) can be serialized as . Serialization is also extensively used in Java Beans. Wiki Markup
An object can be serialized as follows:
Code Block |
---|
ObjectOutputStream oos = new ObjectOutputStream ( new FileOutputStream ("SerialOutput") ); oos.writeObject (someObject); oos.flush ( ); |
The object can then be deserialized as follows:
Code Block |
---|
ObjectInputStream ois = new ObjectInputStream ( new FileInputStream ("SerialOutput") ); someObject = (SomeClass) ois.readObject ( ); |
Serialization captures all the fields of a class, provided the class implements the Serializable
interface, an object including the non-public fields that are not normally accessible (unless the field is declared transient)normally inaccessible, provided that the object's class implements the Serializable
interface. If the byte stream to which the serialized values are written is readable, then the values of the normally inaccessible fields may be readdeduced. Moreover, it may be possible to modify or forge the preserved values so that when the class is deserialized, the values become corrupted.
Introducing a security manager does not fails to prevent the normally inaccessible fields from being serialized and deserialized (although permission must be granted to write to and read from the file or network if the byte stream is being stored or transmitted). Network traffic (including RMI) can be protected, however, by using SSL.
Reflection
Reflection enables a Java program to analyze and modify itself. In particular, a program can find out the values of field variables and change them \[[Forman 05|AA. Bibliography#Forman 05], [Sun 02|AA. Bibliography#Sun 02\]]. The Java reflection API includes a method call that enables fields that are not normally accessible to be accessed under reflection. The following code prints out the names and values of all fields of an object {{someObject}} of class {{SomeClass}}Classes that require special handling during object serialization or deserialization can implement the following methods with exactly the following signatures [API 2006]: Wiki Markup
Code Block |
---|
Fieldprivate [ ] fields = SomeClass.getDeclaredFields(); for (Field fieldsI : fields) { if ( !Modifier.isPublic (fieldsI.getModifiers()) ) { fieldsI.setAccessible (true); } System.out.print("Field: " + fieldsI.getName()); System.out.println(", value: " + fieldsI.get (someObject)); } |
A field could be set to a new value as follows:
Code Block |
---|
String newValue = reader.readLine();
fieldsI.set(someObject,
returnValue(newValue, fieldsI.getType()) );
|
Introducing the default security manager does prevent the fields that would not normally be accessible from being accessed under reflection. The default security manager throws java.security.AccessControlException
in these circumstances. However, it is
possible to grant a permission to override this default behavior: java.lang.reflect.ReflectPermission
can be granted with action suppressAccessChecks
.
The JVM Tool Interface
Wiki Markup |
---|
Java 5 introduced the JVM Tool Interface (JVMTI) \[[Sun 04d|AA. Bibliography#Sun 04d]\], replacing both the JVM Profiler Interface (JVMPI) and the JVM Debug Interface (JVMDI), which are now deprecated. |
The JVMTI contains extensive facilities to find out about the internals of a running JVM, including facilities to monitor and modify a running Java program. These facilities are rather low level and require the use of the Java Native Interface (JNI) and C Language
programming. However, they provide the opportunity to access fields that would not normally be accessible. Also, there are facilities that can change the behavior of a running Java program (for example, threads can be suspended or stopped).
The JVMTI works by using agents that communicate with the running JVM. These agents must be loaded at JVM startup and are usually specified via one of the command line options {{â“agentlib:}} or {{â“agentpath:}}. However, agents can be specified in environment
variables, although this feature can be disabled where security is a concern. The JVMTI is always enabled, and JVMTI agents may run under the default security manager without requiring any permissions to be granted. More work needs to be done to determine under
exactly what circumstances the JVMTI can be misused.
Wiki Markup |
---|
The Java Platform Debugger Architecture (JPDA) builds on the JVMTI and provides highlevel facilities for debugging running Java systems \[[JPDA 2004|AA. Bibliography#JPDA 2004]\]. These include facilities similar to the reflection facilities described above for inspecting and modifying field values. In
particular, there are methods to get and set field and array values. Access control is not enforced so, for example, even the values of private fields can be set. |
Introducing the default security manager means that various permissions must be granted in order for debugging to take place. The following policy file was used to run the JPDS Trace demonstration under the default security manager:
Code Block |
---|
grant {
permission java.io.FilePermission "traceoutput.txt", "read,write";
permission java.io.FilePermission "C:/Program Files/Java/jdk1.5.0_04/lib/tools.jar", "read";
permission java.io.FilePermission "C:/Program", "read,execute";
permission java.lang.RuntimePermission "modifyThread";
permission java.lang.RuntimePermission "modifyThreadGroup";
permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
permission java.lang.RuntimePermission "loadLibrary.dt_shmem";
permission java.util.PropertyPermission "java.home", "read";
permission java.net.SocketPermission "<localhost>", "resolve";
permission com.sun.jdi.JDIPermission "virtualMachineManager";
};
|
Monitoring and Management
Wiki Markup |
---|
Java contains extensive facilities for monitoring and managing a JVM \[[JMX 2006|AA. Bibliography#JMX 2006]\]. In particular, the Java Management Extension (JMX) API enables the monitoring and control of class loading, thread state and stack traces, deadlock detection, memory usage, garbage
collection, operating system information, and other operations \[[Sun 04a|AA. Bibliography#Sun 04a]\]. There are also facilities for logging monitoring and management. A running JVM may be monitored and managed remotely. |
void writeObject(java.io.ObjectOutputStream out) throws IOException
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
|
When a Serializable
class fails to implement writeObject()
, it is serialized using a 'default' method, which serializes all its public, protected, and private fields, except for those marked transient
. Likewise, if a Serializable
class fails to implement readObject()
, it is deserialized by deserializing all its public, protected, and private fields, with the exception of the transient
fields.
When multiple objects are serialized on an ObjectOutputStream
, the ObjectOutputStream
ensures that each object is written to the stream only once. It accomplishes this by retaining a reference (or handle) to each object written to the stream. When a previously written object is written to the stream again, it is replaced with a reference to the originally written data in the stream. This substitution takes place without regard to whether the object's contents have changed in the interim. This table of serialized object references prevents garbage collection of the previously written objects because the garbage collector cannot collect live references. This behavior is both desirable and correct for data that potentially contains arbitrary object graphs, especially when the graphs are fully allocated and constructed prior to serialization. Likewise, the deserialization process can then use these references to efficiently deserialize a complete object graphFor a JVM to be monitored and managed remotely, it must be started with various system properties set (either on the command line or in a configuration file). Also, there are provisions for the monitoring and management to be done securely (by passing the information using SSL, for example) and to require proper authentication of the remote server. However, users may start a JVM with remote monitoring and management enabled with no security for their own purposes, and this would leave the JVM open to compromise
from outsiders. Although a user could not easily turn on remote monitoring and management by accident, they might not realize that starting a JVM so enabled, without any security also switched on, could leave their JVM exposed to outside abuse.