How Java Link Works

I am reading Effective Java , which has the following example. In the example below, the author copies the link to the objects present in the ObjectOutputStream object on the following line

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

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

 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 start field, to which we shouldn't have access public final Date start; // period 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); } } } 
+6
source share
2 answers

These two streaming "ref" s have nothing to do with links in java. (BTW: the byte array has 5 bytes and not only 4, as you noted in the comment). These ten bytes are some kind of inner magic in serialized output. The exact details of this stream format are described in chap. 6.4 "Specification of serialization of Java objects" (the values ​​"71 00 7e 00" appear even in the example below).

The link in the java program contains 4 or 8 bytes, depending on the platform (32 versus 64 bits). This is a pointer to (java-driven) memory where the instance data of the object begins. But, fortunately, you will never have to understand this value in java. I think you can’t even get it.

+2
source

Why does this link point to a date object present in an ObjectOutputStream?

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

what is stored in the link?

The reader saves an identifier and an object reference for that identifier. A link does not store anything except the object to which it points.

+3
source

Source: https://habr.com/ru/post/1011862/


All Articles