Bagikan melalui


Proses eksekusi terkelola

Proses eksekusi terkelola mencakup langkah-langkah berikut, yang dibahas secara rinci nanti dalam topik ini:

  1. Memilih pengompilasi. Untuk mendapatkan manfaat yang diberikan oleh runtime bahasa umum, Anda harus menggunakan satu atau beberapa pengompilasi bahasa yang menargetkan runtime.
  2. Mengkompilasi kode Anda ke bahasa perantara. Mengkompilasi menerjemahkan kode sumber Anda ke dalam bahasa perantara umum (CIL) dan menghasilkan metadata yang diperlukan.
  3. Mengkompilasi CIL ke kode asli. Pada waktu eksekusi, kompilator just-in-time (JIT) menerjemahkan CIL ke dalam kode asli. Selama kompilasi ini, kode harus melewati proses verifikasi yang memeriksa CIL dan metadata untuk mengetahui apakah kode dapat ditentukan sebagai jenis yang aman.
  4. Menjalankan kode. Runtime bahasa umum menyediakan infrastruktur yang memungkinkan eksekusi berlangsung dan layanan yang dapat digunakan selama eksekusi.

Pilih pengkompilasi

Untuk mendapatkan manfaat yang disediakan oleh runtime bahasa umum (CLR), Anda harus menggunakan satu atau beberapa pengompilasi bahasa yang menargetkan runtime, seperti Visual Basic, C#, Visual C++, F#, atau salah satu dari banyak pengompilasi pihak ketiga seperti pengompilasi Eiffel, Perl, atau COBOL.

Karena ini adalah lingkungan eksekusi multibahasa, runtime mendukung berbagai jenis data dan fitur bahasa. Pengompilasi bahasa yang Anda gunakan menentukan fitur runtime mana yang tersedia, dan Anda merancang kode Anda menggunakan fitur-fitur tersebut. Pengompilasi Anda, bukan runtime, menetapkan sintaks yang harus digunakan kode Anda. Jika komponen Anda harus sepenuhnya dapat digunakan oleh komponen yang ditulis dalam bahasa lain, jenis yang diekspor komponen Anda hanya boleh mengekspos fitur bahasa yang disertakan dalam Spesifikasi Bahasa Umum (CLS). Anda dapat menggunakan atribut CLSCompliantAttribute untuk memastikan bahwa kode Anda sesuai dengan CLS. Untuk informasi selengkapnya tentang CLS, lihat Independensi bahasa dan komponen yang tidak bergantung pada bahasa.

Mengkompilasi ke CIL

Saat mengkompilasi ke kode terkelola, pengkompilasi menerjemahkan kode sumber Anda ke dalam bahasa perantara umum (CIL), yang merupakan serangkaian instruksi independen CPU yang dapat dikonversi secara efisien ke kode asli. CIL mencakup instruksi untuk memuat, menyimpan, menginisialisasi, dan memanggil metode pada objek, serta instruksi untuk operasi aritmatika dan logis, alur kontrol, akses memori langsung, penanganan pengecualian, dan operasi lainnya. Sebelum kode dapat dijalankan, CIL harus dikonversi ke kode khusus CPU, biasanya dengan pengkompilasi just-in-time (JIT). Karena runtime bahasa umum menyediakan satu atau beberapa kompilator JIT untuk setiap arsitektur komputer yang didukungnya, set CIL yang sama dapat dikompilasi JIT dan dijalankan pada arsitektur apa pun yang didukung.

Ketika compiler menghasilkan CIL, ia juga menghasilkan metadata. Metadata menjelaskan jenis dalam kode Anda, termasuk definisi setiap jenis, tanda tangan setiap anggota jenis, anggota yang dirujuk kode Anda, dan data lain yang digunakan runtime pada waktu eksekusi. CIL dan metadata terkandung dalam file portable executable (PE) yang didasarkan pada dan yang memperluas Microsoft PE yang diterbitkan dan format file objek umum (COFF) yang digunakan secara historis untuk konten yang dapat dieksekusi. Format file ini, yang mengakomodasi CIL atau kode asli serta metadata, memungkinkan sistem operasi mengenali gambar runtime bahasa umum. Kehadiran metadata dalam file bersama dengan CIL memungkinkan kode Anda menggambarkan dirinya sendiri, yang berarti bahwa tidak perlu pustaka jenis atau Bahasa Definisi Antarmuka (IDL). Runtime menemukan dan mengekstrak metadata dari file sesuai kebutuhan selama eksekusi.

Mengkompilasi CIL ke kode asli

Sebelum Anda dapat menjalankan bahasa perantara umum (CIL), bahasa perantara harus dikompilasi terhadap runtime bahasa umum ke kode asli untuk arsitektur komputer target. .NET menyediakan dua cara untuk melakukan konversi ini:

Kompilasi oleh pengkompilasi JIT

Kompilasi JIT mengonversi CIL ke kode asli sesuai permintaan pada waktu proses aplikasi, ketika konten rakitan dimuat dan dijalankan. Karena runtime bahasa umum menyediakan pengkompilasi JIT untuk setiap arsitektur CPU yang didukung, pengembang dapat membangun serangkaian rakitan CIL yang dapat dikompilasi JIT dan berjalan di komputer yang berbeda dengan arsitektur komputer yang berbeda. Namun, jika kode terkelola Anda memanggil API asli khusus platform atau pustaka kelas khusus platform, kode tersebut hanya akan berjalan pada sistem operasi tersebut.

Kompilasi JIT memperhitungkan kemungkinan bahwa beberapa kode mungkin tidak pernah dipanggil selama eksekusi. Alih-alih menggunakan waktu dan memori untuk mengonversi semua CIL dalam file PE ke kode asli, itu mengonversi CIL sesuai kebutuhan selama eksekusi dan menyimpan kode asli yang dihasilkan dalam memori sehingga dapat diakses untuk panggilan berikutnya dalam konteks proses tersebut. Pemuat membuat dan melampirkan stub ke setiap metode dalam jenis ketika jenis dimuat dan diinisialisasi. Ketika metode dipanggil untuk pertama kalinya, stub meneruskan kontrol ke pengkompilasi JIT, yang mengonversi CIL untuk metode tersebut menjadi kode asli dan memodifikasi stub untuk menunjuk langsung ke kode asli yang dihasilkan. Oleh karena itu, panggilan berikutnya ke metode yang dikompilasi JIT langsung masuk ke kode asli.

Pembuatan kode waktu penginstalan menggunakan NGen.exe

Karena pengkompilasi JIT mengonversi CIL perakitan ke kode asli ketika metode individual yang ditentukan dalam rakitan tersebut dipanggil, itu memengaruhi performa yang merugikan pada run time. Dalam kebanyakan kasus, performa yang berkurang dapat diterima. Lebih penting lagi, kode yang dihasilkan oleh pengompilasi JIT terikat dengan proses yang memicu kompilasi. Ini tidak dapat dibagikan di beberapa proses. Untuk memungkinkan kode yang dihasilkan dibagikan di beberapa pemanggilan aplikasi atau di beberapa proses yang berbagi satu set rakitan, runtime bahasa umum mendukung mode kompilasi sebelumnya. Mode kompilasi sebelumnya ini menggunakan Ngen.exe (Native Image Generator) untuk mengonversi rakitan CIL ke kode asli seperti yang dilakukan pengkompilasi JIT. Namun, pengoperasian Ngen.exe berbeda dari pengompilasi JIT dengan tiga cara:

  • Ini melakukan konversi dari CIL ke kode asli sebelum menjalankan aplikasi alih-alih saat aplikasi sedang berjalan.
  • Ini mengompilasi seluruh perakitan pada satu waktu, dan bukan satu metode pada satu waktu.
  • Ini mempertahankan kode yang dihasilkan di Cache Gambar Asli sebagai file pada disk.

Verifikasi kode

Sebagai bagian dari kompilasinya ke kode asli, kode CIL harus melewati proses verifikasi kecuali administrator telah menetapkan kebijakan keamanan yang memungkinkan kode untuk melewati verifikasi. Verifikasi memeriksa CIL dan metadata untuk mengetahui apakah kode tersebut aman, yang berarti bahwa kode hanya mengakses lokasi memori yang diizinkan untuk diakses. Keamanan jenis membantu mengisolasi objek satu sama lain dan membantu melindunginya dari kerusakan yang tidak disengaja atau berbahaya. Ini juga memberikan jaminan bahwa pembatasan keamanan pada kode dapat diberlakukan dengan andal.

Runtime bergantung pada fakta bahwa pernyataan berikut benar untuk kode yang dapat diverifikasi jenis aman:

  • Referensi ke jenis sangat kompatibel dengan jenis yang dirujuk.
  • Hanya operasi yang ditentukan dengan tepat yang dipanggil pada objek.
  • Identitas adalah apa yang mereka klaim.

Selama proses verifikasi, kode CIL diperiksa dalam upaya untuk mengonfirmasi bahwa kode dapat mengakses lokasi memori dan metode panggilan hanya melalui jenis yang ditentukan dengan benar. Misalnya, kode tidak dapat mengizinkan bidang objek diakses dengan cara yang memungkinkan lokasi memori overrun. Selain itu, verifikasi memeriksa kode untuk menentukan apakah CIL telah dibuat dengan benar, karena CIL yang salah dapat menyebabkan pelanggaran aturan keamanan jenis. Proses verifikasi melewati sekumpulan kode jenis aman yang ditentukan dengan baik, dan hanya melewati kode yang aman. Namun, beberapa kode jenis aman mungkin tidak lolos verifikasi karena beberapa keterbatasan proses verifikasi, dan beberapa bahasa, berdasarkan desain, tidak menghasilkan kode jenis aman yang terverifikasi. Jika kode jenis aman diperlukan oleh kebijakan keamanan tetapi kode tidak lulus verifikasi, pengecualian akan dilemparkan saat kode dijalankan.

Jalankan kode

Runtime bahasa umum menyediakan infrastruktur yang memungkinkan eksekusi terkelola berlangsung dan layanan yang dapat digunakan selama eksekusi. Sebelum metode dapat dijalankan, metode harus dikompilasi ke kode khusus prosesor. Setiap metode di mana CIL telah dihasilkan dikompilasi JIT ketika dipanggil untuk pertama kalinya, lalu dijalankan. Lain kali metode dijalankan, kode asli yang dikompilasi JIT yang ada dijalankan. Proses kompilasi JIT dan kemudian menjalankan kode diulang hingga eksekusi selesai.

Selama eksekusi, kode terkelola menerima layanan seperti pengumpulan sampah, keamanan, interoperabilitas dengan kode tak terkelola, dukungan penelusuran kesalahan lintas bahasa, dan dukungan penyebaran dan penerapan versi yang ditingkatkan.

Di Microsoft Windows Vista, pemuat sistem operasi memeriksa modul terkelola dengan memeriksa sedikit di header COFF. Bit yang diatur menunjukkan modul terkelola. Jika loader mendeteksi modul terkelola, ia memuat mscoree.dll, kemudian _CorValidateImage dan _CorImageUnloading memberi tahu pemuat saat gambar modul terkelola dimuat dan dibongkar. _CorValidateImage melakukan tindakan berikut:

  1. Memastikan bahwa kode tersebut adalah kode terkelola yang valid.
  2. Mengubah titik entri dalam gambar menjadi titik masuk dalam runtime.

Pada Windows 64-bit, _CorValidateImage modifikasi gambar yang ada dalam memori dengan mengubahnya dari format PE32 ke PE32+.

Lihat juga