BigMac66 BigMac66 - 6 months ago 18
Java Question

Serializing java.util.Date

Does anyone know how a java.util.Date gets serialized? I mean explain to me exactly what each byte is? I tried writing out a long then a date and I can see matches but there are other characters that I just don't get.

Our application makes server requests with data which means it gets serialized from client to server. The team that does stress testing uses a tool that captures these requests and modifies them, the problem is they want to process dates and I don't know how to interpret the byte stream. The dude I am talking to seems willing to learn but so far I haven't found anything that I understand to point him to...

Code I used:

FileOutputStream fos = null;
ObjectOutputStream oos = null;
try
{
fos = new FileOutputStream("t.tmp");
oos = new ObjectOutputStream(fos);

Date today = new Date();

oos.writeLong(today.getTime());
oos.writeObject("Today");
oos.writeObject(today);

oos.close();
}
catch(FileNotFoundException e)
{
e.printStackTrace();
}
catch(IOException e)
{
e.printStackTrace();
}


EDIT:

The output from the above is:

"¬í w ,áqÇ-t Todaysr java.util.DatehjKYt xpw ,áqÇ-x"


The long is "w ,áqÇ-" so what is the stuff between the long and the Date object, i.e. "hjKYt xp"

NOTE some the blanks are unprintable characters NULL, SOH, backspace etc. I understand that it is the hex value that matters.

EDIT:

Still having problems. For some reason the serialized HTTP request does not serialize the date exactly like the answer I accepted says. Very close but still different and I don't know why. What's even odder is that when I simply serialize a date it seems to work fine. FYI at worj we use Websphere 6.1 Here are some examples of what is being sent in the request:

lr_start_transaction("20000101");
\\x0Ejava.util.Datehj\\x81\\x01KYt\\x19\\x03\\x00\\x00xpw\\x08\\x00\\x00\\x01,\\xE10\\x0BXxt\\x00\\x08

lr_start_transaction("20000102");
\\x0Ejava.util.Datehj\\x81\\x01KYt\\x19\\x03\\x00\\x00xpw\\x08\\x00\\x00\\x01,\\xE10>\\x9Dxt\\x00\\x08

lr_start_transaction("20000103");
\\x0Ejava.util.Datehj\\x81\\x01KYt\\x19\\x03\\x00\\x00xpw\\x08\\x00\\x00\\x01,\\xE10z\\xDBxt\\x00\\x08


I have been able to identify most fields but not the actual time! E.g the serialVersionUID is
hj\\x81\\x01KYt\\x19


EDIT (FINAL):

I found the date but it was no where near where I expected it! It was well after the sample I had because other data fields were appearing I thought the date was done - it was just fluke that I noticed the hex pattern of the date I was looking for! Example:

lr_start_transaction("20000101");
\\x0Ejava.util.Datehj\\x81\\x01KYt\\x19\\x03\\x00\\x00xpw\\x08\\x00\\x00\\x01,\\xE10\\x0BXxt\\x00\\x08OTTST153t\\x00\\x06/Web2/t\\x00\\x044971t\\x00\\x0B12ce12f737d\\x00\\x00\\x01,\\xE10\\x0BXsq\\x00~\\x00\\x0Fw\\x08\\x00\\x00\\x00\\xDCk\\xE2T\\x80xt


The date value is right at the very end!

Answer
/**
 * Save the state of this object to a stream (i.e., serialize it).
 *
 * @serialData The value returned by <code>getTime()</code>
 *         is emitted (long).  This represents the offset from
 *             January 1, 1970, 00:00:00 GMT in milliseconds.
 */
private void writeObject(ObjectOutputStream s)
     throws IOException
{
    s.writeLong(getTimeImpl());
}

therefore, it's the long value representing the offset from Jan 1 1970 00:00:00 GMT in milliseconds.

EDIT: however this is proceeded and succeeded by some headers:

0x73 - being the code for an ordinary object (TC_OBJECT)

0x72 - being the code for a class description (TC_CLASSDESC)

"java.util.Date" - the name of the class

7523967970034938905L - the serialVersionUID

0|0x02|0x01 - flags including SC_SERIALIZABLE & SC_WRITE_METHOD

0 - number of fields

0x78 - TC_ENDBLOCKDATA

null - there is no superclass descriptor

the time (long milliseconds since epoch)

0x78 - TC_ENDBLOCKDATA