Monday, April 24, 2006

Java Byte Code

เมื่อวันเสาร์ไปประชุมบริษัทฯมา เลยได้รับทราบข่าวว่า
มีลูกค้ารายหนึ่งอยากให้ลอง compile java ใหม่บนเครื่อง Target แทนที่
จะ compile มาจากเครื่อง develop แล้วค่อยเอามาวางบน Target
เหตุผล แค่ เผื่อจะแก้ปัญหาได้
ซึ่งปัจจุบันปัญหาที่หลงเหลือ ก็มีเรื่อง Out of Memory
ซึ่งทาง IBM ที่ australia แนะนำมาแล้วว่่าเกิดขึ้นทีส่วน native
กับ ปัญหา jre ตาย แบบ exception fault
ซึ่ง random เกิด 3-4 เดือนครั้ง

เริ่มสงสัยว่าเป็น idea ใครนี่, อาจารย์ที่ปรึกษา หรือ IBM หรือ บริษัทที่ดูแล mainframe, หรือจากลูกค้าเอง
โดยหลักการแล้ว ผมว่า byte code ที่เกิดจาก platform คนละอัน มันไม่น่าจะทำให้
เกิด exception fault หรือ out of memory ได้นะ

ว่าแล้ว ก็อยากรู้ว่า byte code หน้าตามันเหมือนหรือต่างกันแค่ไหน
ก็เลยลอง compile เปรียบเทียบระหว่าง IBM jdk1.3, Sun jdk1.4 ดู

ลองแบบง่ายๆก่อน
public class HelloWorld {
private String name;

public HelloWorld(String name) {
this.name = name;
}

public String toString() {
return "Hello " + name;
}
}

ผลลัพท์ก็คือ หน้าตา byte code ที่ได้ เหมือนกันเพี๊ยะ ยกเว้นเลข version ที่ส่วน header
// class version 45.3 (196653)
// access flags 33
public class HelloWorld {

// compiled from: HelloWorld.java

// access flags 2
private Ljava/lang/String; name

// access flags 1
public (Ljava/lang/String;)V
L0 (0)
LINENUMBER 5 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.()V
L1 (3)
LINENUMBER 6 L1
ALOAD 0
ALOAD 1
PUTFIELD HelloWorld.name : Ljava/lang/String;
L2 (7)
LINENUMBER 7 L2
RETURN
L3 (9)
LOCALVARIABLE this LHelloWorld; L0 L3 0
LOCALVARIABLE name Ljava/lang/String; L0 L3 1
MAXSTACK = 2
MAXLOCALS = 2

// access flags 1
public toString()Ljava/lang/String;
L0 (0)
LINENUMBER 10 L0
NEW java/lang/StringBuffer
DUP
LDC "Hello "
INVOKESPECIAL java/lang/StringBuffer.(Ljava/lang/String;)V
ALOAD 0
GETFIELD HelloWorld.name : Ljava/lang/String;
INVOKEVIRTUAL java/lang/StringBuffer.append(Ljava/lang/String;)Ljava/lang/StringBuffer;
INVOKEVIRTUAL java/lang/StringBuffer.toString()Ljava/lang/String;
ARETURN
L1 (10)
LOCALVARIABLE this LHelloWorld; L0 L1 0
MAXSTACK = 3
MAXLOCALS = 1
}

เพื่อความแน่ใจ ก็เอา class file ไป compare แบบ binary diff อีกที
ซึ่งผลที่ได้ก็เหมือนกันคือ ต่างกันแค่ byte ที่ 6 กับ 8 เท่านั้น (ส่วน header)

ทดลอง class ที่ซับซ้อนมากขึ้นอีกนิดหนึ่ง ก็คือ Algorithm Shear sort
ผลที่ได้ก็เช่นเดียวกัน ต่างกันแค่ตรงเลข version number

แต่ถ้าลองเอา jdk1.5 มา compile ดู ,คราวนี้สิ เกิดความแตกต่างแน่นอน
อย่าง StringBuffer ก็จะกลายเป็น StringBuilder

Note: ใครที่เคยผ่านหูผ่านตา forum ที่พูดถึงกรณี recompile ก็ช่วยแนะนำด้วยครับ

Related link from Roti

No comments: