JVM Internal, Bagian 1 - Loader Kelas

Terjemahan artikel disiapkan khusus untuk siswa kursus Java Developer .




Dalam seri artikel ini, saya akan berbicara tentang cara kerja Java Virtual Machine. Hari ini kita melihat mekanisme untuk memuat kelas di JVM .

Java Virtual Machine adalah jantung dari ekosistem teknologi Java. Itu memungkinkan untuk program Java untuk menerapkan prinsip "tulis sekali dijalankan di mana-mana". Seperti mesin virtual lainnya, JVM adalah komputer abstrak. Tugas utama JVM adalah untuk memuat file kelas dan menjalankan bytecode yang terkandung di dalamnya.

JVM mencakup berbagai komponen, seperti pemuat Kelas , Pengumpul Sampah (manajemen memori otomatis), juru bahasa, kompiler JIT , dan komponen kontrol aliran. Pada artikel ini, kita akan melihat loader kelas.

Loader kelas memuat file kelas untuk aplikasi Anda dan Java API. Hanya file-file kelas Java API yang benar-benar diperlukan saat menjalankan program dimuat ke mesin virtual.

Kode byte dieksekusi oleh mesin eksekusi.



Apa itu pemuatan kelas?


Pemuatan kelas adalah pencarian dan pemuatan tipe (kelas dan antarmuka) secara dinamis selama eksekusi program. Ketik data dalam file kelas biner.

Langkah-langkah pemuatan kelas


Subsistem pemuat kelas tidak hanya bertanggung jawab untuk menemukan dan mengimpor data kelas biner. Ini juga melakukan validasi kelas yang diimpor, mengalokasikan dan menginisialisasi memori untuk variabel kelas, dan membantu dalam menyelesaikan tautan simbolik. Tindakan ini dilakukan dalam urutan sebagai berikut:

  • Memuat - mencari dan mengimpor data biner untuk suatu jenis berdasarkan namanya, membuat kelas atau antarmuka dari representasi biner ini.
  • Menautkan (menautkan) - verifikasi, persiapan dan, opsional, izin:
    • Verifikasi - verifikasi kebenaran jenis yang diimpor.
    • Persiapan - mengalokasikan memori untuk variabel kelas statis dan menginisialisasi memori dengan nilai default.
    • Resolusi - Konversi tautan tipe simbolik ke tautan langsung.
  • Inisialisasi adalah panggilan ke kode Java yang menginisialisasi variabel kelas dengan nilai awal yang benar.

Catatan - pemuat kelas, selain kelas pemuatan, juga bertanggung jawab untuk menemukan sumber daya. Sumber daya adalah beberapa data (misalnya, file ".class", data konfigurasi, gambar) yang diidentifikasi menggunakan jalur abstrak yang dipisahkan oleh karakter "/". Sumber daya biasanya dikemas dengan aplikasi atau perpustakaan sehingga mereka dapat digunakan dalam aplikasi atau kode perpustakaan.

Mekanisme pemuatan kelas di Jawa


Catatan Penerjemah - bagian ini menjelaskan perilaku untuk java <9, di java 9+ ada perubahan kecil, yang dijelaskan di bawah ini.

Java menggunakan model delegasi pemuatan kelas. Ide dasarnya adalah bahwa setiap pemuat kelas memiliki pemuat "induk". Ketika sebuah kelas dimuat , loader β€œmendelegasikan” pencarian kelas ke induknya sebelum mencari sendiri kelasnya.

Model pendelegasian loader kelas adalah grafik loader yang menyampaikan permintaan muatan satu sama lain. Akar dari grafik ini adalah bootloader bootstrap. Loader kelas dibuat dengan satu orangtua yang kepadanya mereka dapat mendelegasikan beban, dan mencari kelas di tempat-tempat berikut:

  • Cache
  • Orang tua
  • Bootloader sendiri

Loader kelas pertama memeriksa untuk melihat apakah telah memuat kelas sebelumnya. Jika demikian, maka kelas yang sama yang dikembalikan terakhir kali dikembalikan (kelas disimpan dalam cache). Jika tidak, orang tua diberikan kesempatan untuk memuat kelas. Kedua langkah ini diulang secara mendalam secara rekursif. Jika induk mengembalikan nol (atau melempar ClassNotFoundException ), maka loader mencari kelas sendiri.

Kelas dimuat oleh loader yang paling dekat dengan root, karena hak untuk memuat pertama kelas selalu diberikan kepada induk loader. Ini memungkinkan loader melihat hanya kelas yang dimuat secara independen, oleh induk atau leluhurnya. Itu tidak bisa melihat kelas dimuat oleh anak loader.

Java SE Platform API secara historis mendefinisikan dua pemuat kelas:

Bootstrap class loader (dasar, loader primer) - memuat kelas dari bootstrap classpath.

Pemuat kelas sistem (pemuat induk ) - kelas induk untuk pemuat kelas baru dan, biasanya, pemuat kelas yang digunakan untuk memuat dan menjalankan aplikasi.

JDK 9+ Pemuat Kelas


Pemuat kelas aplikasi - umumnya digunakan untuk memuat kelas aplikasi dari classpath. Ini juga merupakan bootloader default untuk beberapa modul JDK yang berisi utilitas atau mengekspor API utilitas. ( Catatan Penerjemah: misalnya, jdk.jconsole , jdk.jshell , dll. )

Loader kelas platform - memuat yang dipilih (berdasarkan keamanan / izin) modul Java SE dan JDK. Misalnya, java.sql.

Bootstrap class loader - Memuat modul Java SE dan JDK inti.

Tiga pemuat kelas bawaan ini bekerja bersama sebagai berikut:

  • Pemuat kelas aplikasi pertama mencari modul bernama yang ditentukan untuk semua pemuat terintegrasi. Jika modul yang sesuai ditentukan untuk salah satu dari pemuat ini, maka pemuat ini memuat kelas. Jika kelas tidak ditemukan dalam modul bernama yang ditentukan untuk salah satu pemuat ini, maka pemuat kelas aplikasi mendelegasikannya ke induk. Jika kelas tidak ditemukan oleh induk, maka pemuat kelas aplikasi mencarinya di classpath. Kelas yang ditemukan di classpath diambil sebagai anggota modul yang tidak disebutkan namanya dari pemuat ini.
  • Loader kelas platform mencari modul yang ditentukan untuk semua loader terintegrasi. Jika modul yang sesuai ditentukan untuk salah satu dari pemuat ini, maka pemuat ini memuat kelas. Jika kelas tidak ditemukan dalam modul bernama yang ditentukan untuk salah satu pemuat ini, maka pemuat kelas platform mendelegasikannya ke induk.
  • Loader kelas bootstrap mencari modul bernama yang ditentukan untuk dirinya sendiri. Jika kelas tidak ditemukan dalam modul bernama yang ditentukan untuk bootloader bootstrap, maka bootstrap loader mencari file dan direktori yang ditambahkan ke bootstrap classpath menggunakan parameter -Xbootclasspath / a (memungkinkan Anda untuk menambahkan file dan direktori ke bootpath bootpath classpath). Kelas yang ditemukan di bootstrap classpath dimuat sebagai anggota modul yang tidak disebutkan namanya dari pemuat ini.

Untuk melihat pemuat kelas bawaan, Anda dapat menggunakan kode berikut:

 package ru.deft.homework; import java.sql.Date; public class BuiltInClassLoadersDemo { public static void main(String[] args) { BuiltInClassLoadersDemo demoObject = new BuiltInClassLoadersDemo(); ClassLoader applicationClassLoader = demoObject.getClass().getClassLoader(); printClassLoaderDetails(applicationClassLoader); // java.sql classes are loaded by platform classloader java.sql.Date now = new Date(System.currentTimeMillis()); ClassLoader platformClassLoder = now.getClass().getClassLoader(); printClassLoaderDetails(platformClassLoder); // java.lang classes are loaded by bootstrap classloader ClassLoader bootstrapClassLoder = args.getClass().getClassLoader(); printClassLoaderDetails(bootstrapClassLoder); } private static void printClassLoaderDetails(ClassLoader classLoader) { // bootstrap classloader is represented by null in JVM if (classLoader != null) { System.out.println("ClassLoader name : " + classLoader.getName()); System.out.println("ClassLoader class : " + classLoader.getClass().getName()); } else { System.out.println("Bootstrap classloader"); } } } 

Dengan menjalankan kode ini di Amazon Corretto 11.0.3 yang diinstal pada saya, kami mendapatkan hasil berikut:

 ClassLoader name : app ClassLoader class : jdk.internal.loader.ClassLoaders$AppClassLoader ClassLoader name : platform ClassLoader class : jdk.internal.loader.ClassLoaders$PlatformClassLoader Bootstrap classloader 

Anda dapat mempelajari lebih lanjut tentang API ClassLoader di sini (JDK 11) .

Source: https://habr.com/ru/post/id468193/


All Articles