Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does referencing work in Java

I am reading a book Effective Java which has the following example. In the below example author copies the reference of objects present in the ObjectOutputStream by the following line

byte[] ref = {0x71, 0, 0x7e, 0, 5}; // Ref #5 

Why does this reference point to the date object present in the ObjectOutputStream? what is stored in a reference?

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;

final class Period {
    private final Date start;
    private final Date end;

    /**
     * @param start the beginning of the period
     * @param end the end of the period; must not precede start * @throws IllegalArgumentException
     *        if start is after end
     * @throws NullPointerException if start or end is null
     */
    public Period(Date start, Date end) {
        this.start = new Date(start.getTime());
        this.end = new Date(end.getTime());
        if (this.start.compareTo(this.end) > 0)
            throw new IllegalArgumentException(start + " after " + end);
    }

    public Date start() {
        return new Date(start.getTime());
    }

    public Date end() {
        return new Date(end.getTime());
    }

    public String toString() {
        return start + " - " + end;
    }
    // Remainder omitted
}


public class MutablePeriod {
    // A period instance
    public final Period period;
    // period's start field, to which we shouldn't have access
    public final Date start;
    // period's end field, to which we shouldn't have access
    public final Date end;

    public MutablePeriod() {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(bos);

            // Serialize a valid Period instance
            out.writeObject(new Period(new Date(), new Date()));
            /*
             * Append rogue "previous object refs" for internal * Date fields in Period. For
             * details, see "Java Object Serialization Specification," Section 6.4.
             */
            byte[] ref = {0x71, 0, 0x7e, 0, 5}; // Ref #5 
            bos.write(ref); // The start field
            ref[4] = 4; // Ref#4
            bos.write(ref); // The end field
            // Deserialize Period and "stolen" Date references
            ObjectInputStream in =
                    new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
            period = (Period) in.readObject();
            start = (Date) in.readObject();
            end = (Date) in.readObject();

        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}
like image 550
raju Avatar asked Oct 30 '16 17:10

raju


2 Answers

Why does this reference point to the date object present in the ObjectOutputStream?

When the first object is written, each object (and class) is given an id. When you add the appropriate bytes so that the reader will read the reference #5 you get this object reference. It just happens that the two date objects are #4 and #5, but if you wrote different data they would have a different id.

what is stored in a reference?

The reader stores the id and the reference to the object for that id. A reference doesn't store anything except the object it points to.

like image 191
Peter Lawrey Avatar answered Oct 22 '22 07:10

Peter Lawrey


These two streamed "ref"s have nothing to do with references in java. (BTW: the byte array has 5 bytes and not only 4 as you mention in a comment). These ten bytes are some internal magic in the serialized output. The exact details about this stream format is described in chap. 6.4 of "Java Object Serialization Specification" (The values "71 00 7e 00" arise even in the example there at the bottom).

A reference in a java program contains either 4 or 8 bytes, depending on the platform (32 vs. 64 bit). It is a pointer into (java managed) memory where the data of the object instance starts. But thankfully you never have to deal with this value in java. I think you cannot even access it.

like image 45
Heri Avatar answered Oct 22 '22 05:10

Heri