มีแนวคิดของฟังก์ชันแบบอินไลน์ใน java หรือไม่หรือแทนที่อย่างอื่น? ถ้ามีใช้อย่างไร? ฉันได้ยินมาpublic
แล้วstatic
และfinal
วิธีการเป็นฟังก์ชันแบบอินไลน์ เราสามารถสร้างฟังก์ชันอินไลน์ของเราเองได้หรือไม่?
มีแนวคิดของฟังก์ชันแบบอินไลน์ใน java หรือไม่หรือแทนที่อย่างอื่น? ถ้ามีใช้อย่างไร? ฉันได้ยินมาpublic
แล้วstatic
และfinal
วิธีการเป็นฟังก์ชันแบบอินไลน์ เราสามารถสร้างฟังก์ชันอินไลน์ของเราเองได้หรือไม่?
คำตอบ:
ใน Java การเพิ่มประสิทธิภาพมักจะทำที่ระดับ JVM ในขณะรันไทม์ JVM จะทำการวิเคราะห์ที่ "ซับซ้อน" บางอย่างเพื่อกำหนดวิธีการที่จะอินไลน์ มันสามารถก้าวร้าวในการอินไลน์และ Hotspot JVM สามารถอินไลน์วิธีการที่ไม่ใช่ขั้นสุดท้ายได้
คอมไพเลอร์ java แทบจะไม่อินไลน์การเรียกใช้เมธอดใด ๆ เลย (JVM ทำสิ่งนั้นทั้งหมดที่รันไทม์) พวกเขาทำค่าคงที่ในการคอมไพล์แบบอินไลน์ (เช่นค่าดั้งเดิมคงที่สุดท้าย) แต่ไม่ใช่วิธีการ
สำหรับแหล่งข้อมูลเพิ่มเติม:
บทความ: Java HotSpot Performance Engine: Method Inlining Example
Wiki: Inlining ใน OpenJDKไม่ได้รับการเติมเต็ม แต่มีลิงก์ไปยังการสนทนาที่เป็นประโยชน์
ไม่ไม่มีฟังก์ชัน inlineใน java ได้คุณสามารถใช้วิธีการคงที่สาธารณะที่ใดก็ได้ในรหัสเมื่อวางไว้ในคลาสสาธารณะ คอมไพเลอร์ java อาจทำการขยายแบบอินไลน์บนวิธีการแบบคงที่หรือขั้นสุดท้าย แต่ไม่รับประกัน
โดยทั่วไปแล้วการเพิ่มประสิทธิภาพโค้ดดังกล่าวจะกระทำโดยคอมไพเลอร์ร่วมกับ JVM / JIT / HotSpot สำหรับส่วนของโค้ดที่ใช้บ่อยมาก นอกจากนี้แนวคิดการเพิ่มประสิทธิภาพอื่น ๆ เช่นการประกาศการลงทะเบียนของพารามิเตอร์จะไม่เป็นที่รู้จักใน java
การเพิ่มประสิทธิภาพไม่สามารถบังคับโดยการประกาศใน java แต่ทำได้โดยคอมไพเลอร์และ JIT ในภาษาอื่น ๆ การประกาศเหล่านี้มักเป็นเพียงคำแนะนำของคอมไพเลอร์ (คุณสามารถประกาศพารามิเตอร์รีจิสเตอร์ได้มากกว่าที่โปรเซสเซอร์มีส่วนที่เหลือจะถูกละเว้น)
การประกาศเมธอด java แบบคงที่ขั้นสุดท้ายหรือไพรเวตยังเป็นคำแนะนำสำหรับคอมไพเลอร์ คุณควรใช้ แต่ไม่มีการรับประกัน ประสิทธิภาพของ Java เป็นแบบไดนามิกไม่ใช่แบบคงที่ การโทรเข้าระบบครั้งแรกมักจะช้าเนื่องจากการโหลดคลาส การโทรครั้งต่อไปจะเร็วกว่า แต่ขึ้นอยู่กับหน่วยความจำและรันไทม์การโทรที่พบบ่อยที่สุดจะได้รับการปรับให้เหมาะสมกับระบบที่กำลังทำงานอยู่ดังนั้นเซิร์ฟเวอร์อาจเร็วขึ้นในระหว่างรันไทม์!
final
ไม่ส่งผลกระทบต่อ JIT inlining
Java ไม่มีวิธีแนะนำด้วยตนเองว่าควรใช้วิธีการแบบอินไลน์ ดังที่ @notnoop กล่าวไว้ในความคิดเห็นโดยทั่วไปแล้ว JVM จะทำอินไลน์ในเวลาดำเนินการ
jdk.internal.vm.annotation.ForceInline
สิ่งที่คุณพูดข้างต้นถูกต้อง บางครั้งเมธอดสุดท้ายถูกสร้างเป็นแบบอินไลน์ แต่ไม่มีวิธีอื่นในการสร้างฟังก์ชันอินไลน์ใน java อย่างชัดเจน
final
ไม่ได้สร้างความแตกต่างว่าเมธอดอยู่ในบรรทัดหรือไม่
ตัวอย่างชีวิตจริง:
public class Control {
public static final long EXPIRED_ON = 1386082988202l;
public static final boolean isExpired() {
return (System.currentTimeMillis() > EXPIRED_ON);
}
}
จากนั้นในชั้นเรียนอื่นฉันสามารถออกได้หากรหัสหมดอายุ ถ้าฉันอ้างอิงตัวแปร EXPIRED_ON จากคลาสอื่นค่าคงที่จะอยู่ในบรรทัดของโค้ดไบต์ทำให้ยากมากที่จะติดตามตำแหน่งทั้งหมดในโค้ดที่ตรวจสอบวันหมดอายุ อย่างไรก็ตามหากคลาสอื่นเรียกใช้เมธอด isExpired () เมธอดจริงจะถูกเรียกซึ่งหมายความว่าแฮ็กเกอร์สามารถแทนที่เมธอด isExpired ด้วยวิธีอื่นซึ่งจะคืนค่าเป็นเท็จเสมอ
ฉันเห็นด้วยเป็นเรื่องดีมากที่จะบังคับให้คอมไพเลอร์อินไลน์วิธีสุดท้ายแบบคงที่ไปยังคลาสทั้งหมดที่อ้างถึง ในกรณีนี้คุณไม่จำเป็นต้องรวมคลาส Control ด้วยซ้ำเพราะไม่จำเป็นต้องใช้ในรันไทม์
จากการวิจัยของฉันสิ่งนี้ไม่สามารถทำได้ บางทีเครื่องมือ Obfuscator บางตัวสามารถทำได้หรือคุณอาจปรับเปลี่ยนกระบวนการสร้างของคุณเพื่อแก้ไขแหล่งที่มาก่อนที่จะคอมไพล์
สำหรับการพิสูจน์ว่าเมธอดจากคลาสควบคุมถูกวางแบบอินไลน์ไปยังคลาสอื่นระหว่างคอมไพล์หรือไม่ให้ลองรันคลาสอื่นโดยไม่มีคลาสคอนโทรลในคลาสพา ธ
มีวิธีที่เรียกว่าเมธอด "inline" ใน java ได้ แต่ขึ้นอยู่กับ jvm หลังจากคอมไพล์แล้วหากรหัสเครื่องของเมธอดน้อยกว่า 35 ไบต์โค้ดจะถูกโอนไปยังเมธอดแบบอินไลน์ทันทีหากโค้ดเครื่องของเมธอดมีขนาดน้อยกว่า 325 ไบต์ก็สามารถโอนไปยังเมธอดแบบอินไลน์ได้ขึ้นอยู่กับ jvm
ดูเหมือนว่าจะไม่มี แต่คุณสามารถใช้วิธีแก้ปัญหานี้โดยใช้ guava หรือการใช้งานคลาส Function ที่เทียบเท่าได้เนื่องจากคลาสนั้นง่ายมากเช่น:
assert false : new com.google.common.base.Function<Void,String>(){
@Override public String apply(Void input) {
//your complex code go here
return "weird message";
}}.apply(null);
ใช่นี่เป็นรหัสตายเพียงเพื่อเป็นตัวอย่างวิธีสร้างบล็อกโค้ดที่ซับซ้อน (ภายใน {}) เพื่อทำบางสิ่งที่เฉพาะเจาะจงซึ่งไม่ควรรบกวนเราในการสร้างวิธีการใด ๆ สำหรับมัน AKA อินไลน์!
Java9 มีคอมไพเลอร์ "Ahead of time" ที่ทำการเพิ่มประสิทธิภาพหลายอย่างในเวลาคอมไพล์แทนที่จะเป็นรันไทม์ซึ่งสามารถมองเห็นได้ว่าเป็นอินไลน์