คอมไพเลอร์ Java AOT ทำงานอย่างไร


18

มีเครื่องมือไม่กี่อย่างที่นั่น ( Excelsior JET , ฯลฯ ) ที่อ้างว่าแปลงแอป Java ให้เป็นไฟล์ปฏิบัติการดั้งเดิม ( *.exe) อย่างไรก็ตามมันเป็นความเข้าใจของฉันว่าเครื่องมือเหล่านี้เป็นเพียงการสร้าง wrappers พื้นเมืองที่เรียกใช้ / ดำเนินการjavaจากเปลือกหรือบรรทัดคำสั่ง

หากความเข้าใจนั้นไม่ถูกต้องฉันไม่เห็นว่ามันจะเป็นไปได้ หาก JVM ที่ทำงานอยู่ ( javaกระบวนการ) เป็นล่ามประสิทธิภาพสูงโดยการโหลด bytecode จาก Java classfiles ในทันทีฉันไม่เห็นว่าแอป Java (คอลเลกชันของไฟล์ bytecode ที่ทำหน้าที่เป็นอินพุตของ JVM) จะเป็นอย่างไร แปลงเป็นปฏิบัติการจริง ๆ

นี้เป็นเพราะกระบวนการ JVM เป็นแล้วปฏิบัติการพื้นเมืองที่ใช้ชุดของไฟล์ bytecode เป็น input หากต้องการรวมไฟล์ bytecode เหล่านั้นและกระบวนการ JVM เข้าด้วยกันเป็นโปรแกรมปฏิบัติการแบบเนทีฟแบบรวมไม่สามารถทำได้โดยไม่ต้องเขียน JVM และยกเลิกการแยกจากข้อมูลจำเพาะ JVM อย่างสมบูรณ์

ดังนั้นผมจึงถาม: วิธีการทำเครื่องมือเหล่านี้จริง "เปลี่ยน" คลาสไฟล์จาวาเป็นปฏิบัติการพื้นเมืองหรือพวกเขา?

คำตอบ:


26

โปรแกรมทั้งหมดมีสภาพแวดล้อมรันไทม์ เรามักจะลืมสิ่งนี้ แต่มันอยู่ที่นั่น lib มาตรฐานสำหรับ C ที่ล้อมรอบการเรียกระบบไปยังระบบปฏิบัติการ Objective-C มีรันไทม์ที่ล้อมรอบการส่งผ่านข้อความทั้งหมด

ด้วย Java รันไทม์คือ JVM การใช้งานจาวาส่วนใหญ่ที่คนคุ้นเคยจะคล้ายกับ HotSpot JVM ซึ่งเป็นล่ามรหัสไบต์และคอมไพเลอร์ JIT

สิ่งนี้ไม่จำเป็นต้องเป็นการใช้งานเพียงอย่างเดียว ไม่มีอะไรบอกได้เลยว่าคุณไม่สามารถสร้างรันไทม์ lib-esque มาตรฐานสำหรับ Java และรวบรวมรหัสไปยังรหัสเครื่องดั้งเดิมและเรียกใช้ภายในรันไทม์ที่จัดการการโทรสำหรับวัตถุใหม่ใน mallocs และการเข้าถึงไฟล์เข้าสู่การเรียกระบบบนเครื่อง และนั่นคือสิ่งที่คอมไพเลอร์ก่อนเวลา (AOT มากกว่า JIT) ทำ โทรรันไทม์ว่าสิ่งที่คุณจะ ... คุณสามารถเรียกมันว่าการดำเนินงาน JVM (และก็ไม่เป็นไปตามข้อกำหนด JVM) หรือสภาพแวดล้อมรันไทม์หรือ lib มาตรฐานสำหรับ Java มันอยู่ที่นั่นและมันก็ทำสิ่งเดียวกัน

มันสามารถทำได้โดยการปรับใช้ซ้ำjavacเพื่อกำหนดเป้าหมายเครื่องดั้งเดิม (นั่นคือสิ่งที่GCJทำ) หรืออาจทำได้ด้วยการแปลรหัสไบต์ที่สร้างโดยjavacเป็นรหัสเครื่อง (หรือไบต์) สำหรับเครื่องอื่น - นั่นคือสิ่งที่ Android ทำ จากวิกิพีเดียนั่นคือสิ่งที่ Excelsior JET ทำเช่นกัน ("คอมไพเลอร์แปลงรหัส Java byte แบบพกพาให้เป็นไฟล์ปฏิบัติการที่ปรับแต่งแล้วสำหรับฮาร์ดแวร์และระบบปฏิบัติการ (OS)") และRoboVM ก็เหมือนกัน

มีภาวะแทรกซ้อนเพิ่มเติมกับ Java ซึ่งหมายความว่ายากมากที่จะทำตามวิธีการพิเศษ การโหลดคลาส ( class.forName()) หรือวัตถุพร็อกซีแบบไดนามิกจำเป็นต้องใช้ไดนามิคที่คอมไพเลอร์ AOT ไม่สามารถจัดหาได้ง่ายดังนั้น JVM ที่เกี่ยวข้องจะต้องมีคอมไพเลอร์ JIT (Excelsior JET) หรือล่าม (GCJ) เพื่อจัดการคลาสที่ไม่สามารถคอมไพล์ได้ พื้นเมือง.

โปรดจำไว้ว่าJVM เป็นข้อกำหนด , กับการใช้งานจำนวนมาก ไลบรารีมาตรฐาน C ยังเป็นข้อกำหนดที่มีการนำไปใช้งานที่แตกต่างกันมากมาย

ด้วย Java8 มีการทำงานที่เป็นธรรมบนการคอมไพล์ AOT ที่ดีที่สุดเพียงคนเดียวที่สามารถสรุป AOT โดยทั่วไปภายในขอบเขตของกล่องข้อความ อย่างไรก็ตามในการประชุม JVM Language Summit ประจำปี 2558 (สิงหาคม 2558) มีการนำเสนอ: Java Goes AOT (วิดีโอ youtube) วิดีโอนี้มีความยาว 40 นาทีและไปสู่ด้านเทคนิคและการวัดประสิทธิภาพเชิงลึก


ขออภัยฉันไม่ทราบเกี่ยวกับสิ่งนี้มาก แต่นี่หมายความว่า java นั้นมีอยู่ในตอนนี้หรือไม่ หรือหมายความว่ามีแฟล็กคอมไพเลอร์ใหม่ที่ช่วยให้เราสามารถรวบรวมโปรแกรมจาวาเป็นโค้ดเนทีฟหากเราต้องการและเรายังมีตัวเลือกในการคอมไพล์โค้ดไบต์เช่นกัน?
Pavel

@ paulpaul1076 ฉันขอแนะนำให้ดูวิดีโอที่ฉันเชื่อมโยง มันมีอะไรที่มากกว่านั้นนิดหน่อยกว่าที่ฉันจะสามารถแสดงความคิดเห็นได้

4

gcj ตัวอย่าง runnable น้อยที่สุด

คุณสามารถสังเกตการใช้งานโอเพ่นซอร์สเช่นgcj(ล้าสมัยแล้ว) เช่นไฟล์ Java:

public class Main {
    public static void main(String args[]) {
        System.out.println("hello world");
    }
}

จากนั้นรวบรวมและเรียกใช้ด้วย:

gcj -c Main.java
gcj --main=Main -o Main Main.o
./Main

ตอนนี้คุณมีอิสระที่จะถอดรหัสและดูว่ามันทำงานอย่างไร

file Main.o บอกว่ามันเป็นไฟล์เอลฟ์

readelf -d Main | grep NEEDED บอกว่ามันขึ้นอยู่กับไลบรารีแบบไดนามิก:

0x0000000000000001 (NEEDED)             Shared library: [libgcj.so.14]
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

ดังนั้นlibgcj.soต้องเป็นที่ที่มีการใช้งานฟังก์ชัน Java

จากนั้นคุณสามารถคอมไพล์มันด้วย:

objdump -Cdr Main.o

และดูว่ามีการนำไปใช้อย่างไร

ดูเหมือน C ++, ชื่อ mangling และการเรียกฟังก์ชัน polymorphic ทางอ้อมมากมาย

ฉันสงสัยว่าคอลเล็กชันขยะเริ่มต้นอย่างไรมันจะคุ้มค่าที่จะดู: /programming/7100776/garbage-collection-implementation-in Implementation-in-compiled-language และภาษาอื่น ๆ ที่รวบรวมด้วย GC เช่น Go

ทดสอบบน Ubuntu 14.04, GCC 4.8.4

ดูที่https://en.wikipedia.org/wiki/Android_Runtimeซึ่งเป็นกระดูกสันหลังของ Android 5 เป็นต้นไปซึ่งใช้ AOT เต็มรูปแบบเพื่อเพิ่มประสิทธิภาพแอป Android

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.