ให้เริ่มด้วยคลาสง่าย ๆ สองคลาส:
package com.michaelt.so.supers;
public class Sup {
int methodA(int a, int b) {
return a + b;
}
}
แล้ว
package com.michaelt.so.supers;
public class Sub extends Sup {
@Override
int methodA(int a, int b) {
return super.methodA(a, b);
}
}
รวบรวม methodA และดูรหัสไบต์ที่ได้รับ:
methodA(II)I
L0
LINENUMBER 6 L0
ALOAD 0
ILOAD 1
ILOAD 2
INVOKESPECIAL com/michaelt/so/supers/Sup.methodA (II)I
IRETURN
L1
LOCALVARIABLE this Lcom/michaelt/so/supers/Sub; L0 L1 0
LOCALVARIABLE a I L0 L1 1
LOCALVARIABLE b I L0 L1 2
MAXSTACK = 3
MAXLOCALS = 3
และคุณสามารถดูได้ที่นั่นด้วยวิธีการที่เรียกว่าการค้นหามันเทียบกับวิธีการเรียน Sup ()
opcode ที่ตอบสนองต่อการร้องขอมีตรรกะดังต่อไปนี้:
- ถ้า C มีการประกาศสำหรับวิธีการอินสแตนซ์ที่มีชื่อและตัวอธิบายเป็นวิธีการแก้ไขแล้ววิธีการนี้จะถูกเรียก กระบวนการค้นหาสิ้นสุดลง
- มิฉะนั้นถ้า C มีซูเปอร์คลาสขั้นตอนการค้นหาเดียวกันนี้จะดำเนินการซ้ำโดยใช้ซูเปอร์คลาสโดยตรงของ C วิธีการที่จะเรียกใช้เป็นผลมาจากการเรียกซ้ำของขั้นตอนการค้นหานี้ซ้ำ
- มิฉะนั้นจะมีการเพิ่ม AbstractMethodError
ในกรณีนี้ไม่มีวิธีอินสแตนซ์ที่มีชื่อและตัวบอกลักษณะเหมือนกันในชั้นเรียนของเขาดังนั้นสัญลักษณ์แสดงหัวข้อแรกจะไม่เริ่มทำงาน กระสุนนัดที่สองอย่างไรก็ตามจะมีซูเปอร์คลาสและเรียกใช้เมธอดของซุปเปอร์เอ
คอมไพเลอร์ไม่ได้อินไลน์สิ่งนี้และไม่มีสำเนาของแหล่งที่มาของ Sup ในคลาส
อย่างไรก็ตามเรื่องยังไม่เสร็จ นี่เป็นเพียงรหัสที่คอมไพล์แล้ว เมื่อโค้ดเข้าสู่ JVM แล้ว HotSpotสามารถเข้าร่วมได้
น่าเสียดายที่ฉันไม่รู้มากเกี่ยวกับเรื่องนี้ดังนั้นฉันจะอุทธรณ์ต่อผู้มีอำนาจในเรื่องนี้และไปที่Inlining ใน Javaที่มีการกล่าวว่า HotSpot สามารถใช้วิธีการแบบอินไลน์ (แม้ไม่ใช่วิธีสุดท้าย)
การไปที่เอกสารนั้นมีข้อสังเกตว่าหากการเรียกใช้เมธอดเฉพาะกลายเป็นฮอตสปอตแทนที่จะทำการค้นหาในแต่ละครั้งข้อมูลนี้สามารถ inline - คัดลอกโค้ดจาก Sup methodA () ไปยัง Sub methodA () ได้อย่างมีประสิทธิภาพ
สิ่งนี้ทำที่รันไทม์ในหน่วยความจำขึ้นอยู่กับว่าแอ็พพลิเคชันทำงานอย่างไรและการปรับแต่งใดที่จำเป็นต่อการเร่งประสิทธิภาพ
ตามที่ระบุไว้ในHotSpot Internals สำหรับ OpenJDK "วิธีการมักจะ inline การร้องขอแบบคงที่ส่วนตัวสุดท้ายและ / หรือ" พิเศษ "ง่ายต่อการแทรกแบบอินไลน์
หากคุณขุดลงไปในตัวเลือกสำหรับ JVMคุณจะพบตัวเลือก-XX:MaxInlineSize=35
(35 เป็นค่าเริ่มต้น) ซึ่งเป็นจำนวนไบต์สูงสุดที่สามารถ inlined ฉันจะชี้ให้เห็นว่านี่คือเหตุผลที่ Java ชอบที่จะมีวิธีการเล็ก ๆ น้อย ๆ มากมาย - เพราะพวกเขาสามารถอินไลน์ได้ง่าย วิธีการขนาดเล็กเหล่านั้นจะเร็วขึ้นเมื่อพวกเขาถูกเรียกใช้มากขึ้นเพราะพวกเขาสามารถ inline และในขณะที่เราสามารถเล่นกับหมายเลขนั้นและทำให้ใหญ่ขึ้นมันอาจทำให้การเพิ่มประสิทธิภาพอื่น ๆ มีประสิทธิภาพน้อยลง (คำถาม SO ที่เกี่ยวข้อง: HotSpot JIT อินไลน์กลยุทธ์ซึ่งชี้ให้เห็นตัวเลือกอื่น ๆ จำนวนมากที่จะมองหาที่ภายในของการทำอินไลน์ที่ HotSpot กำลังทำอยู่)
ดังนั้นไม่ - รหัสไม่ได้ถูกขีดเส้นใต้เวลารวบรวม และใช่ - โค้ดอาจถูกแทรกในรันไทม์ได้เป็นอย่างดีหากการปรับประสิทธิภาพให้เหมาะสมรับประกัน
และสิ่งที่ฉันเขียนเกี่ยวกับ HotSpot inlining นั้นใช้ได้กับ HotSpot JVM ที่ Oracle จัดจำหน่ายเท่านั้น หากคุณดูรายการ Java virtual machine ของวิกิพีเดียมีมากกว่า HotSpot และวิธีที่ JVMs จัดการอินไลน์สามารถแตกต่างอย่างสิ้นเชิงกับสิ่งที่ฉันได้อธิบายไว้ข้างต้น Apache Harmony, Dalvik, ART - สิ่งต่าง ๆ อาจทำงานแตกต่างกันตรงนั้น