Saya tahu ini mungkin pertanyaan konyol bagi pembuat kode berpengalaman. Tetapi saya memiliki pustaka (klien http) yang dibutuhkan oleh beberapa kerangka kerja / botol lain yang digunakan dalam proyek saya. Tetapi semuanya membutuhkan versi utama yang berbeda seperti:
httpclient-v1.jar => Required by cralwer.jar
httpclient-v2.jar => Required by restapi.jar
httpclient-v3.jar => required by foobar.jar
Apakah classloader cukup cerdas untuk memisahkannya? Kemungkinan besar tidak? Bagaimana Classloader menangani ini, jika Kelas sama di ketiga toples. Yang mana yang dimuat dan mengapa?
Apakah Classloader hanya mengambil satu botol atau mencampur kelas secara sembarangan? Jadi misalnya jika sebuah kelas dimuat dari Versi-1.jar, semua kelas lain yang dimuat dari classloader yang sama akan masuk ke dalam jar yang sama?
Bagaimana Anda menangani masalah ini?
Apakah ada beberapa trik untuk entah bagaimana "memasukkan" toples ke dalam "required.jar" sehingga terlihat sebagai "satu unit / paket" oleh Classloader
, atau entah bagaimana terkait?
sumber
Setiap beban kelas memilih tepat satu kelas. Biasanya yang pertama ditemukan.
OSGi bertujuan untuk memecahkan masalah beberapa versi dari jar yang sama. Equinox dan Apache Felix adalah implementasi sumber terbuka yang umum untuk OSGi.
sumber
Classloader akan memuat kelas dari jar yang kebetulan berada di jalur kelas terlebih dahulu. Biasanya, versi pustaka yang tidak kompatibel akan memiliki perbedaan dalam paket, Tetapi dalam kasus yang tidak mungkin mereka benar-benar tidak kompatibel dan tidak dapat diganti dengan satu - coba jarjar.
sumber
Classloader memuat kelas sesuai permintaan. Ini berarti bahwa kelas yang diperlukan terlebih dahulu oleh aplikasi Anda dan pustaka terkait akan dimuat sebelum kelas lain; permintaan untuk memuat kelas-kelas dependen biasanya dikeluarkan selama proses pemuatan dan penautan dari kelas yang bergantung.
Anda kemungkinan besar akan menemukan
LinkageError
pernyataan bahwa definisi kelas duplikat telah ditemukan karena classloader biasanya tidak mencoba menentukan kelas mana yang harus dimuat terlebih dahulu (jika ada dua atau lebih kelas dengan nama yang sama yang ada di classpath loader). Terkadang, classloader akan memuat kelas pertama yang terjadi di classpath dan mengabaikan kelas duplikat, tetapi ini bergantung pada implementasi loader.Praktik yang disarankan untuk mengatasi jenis error tersebut adalah dengan menggunakan classloader terpisah untuk setiap kumpulan pustaka yang memiliki dependensi yang bertentangan. Dengan begitu, jika classloader mencoba memuat class dari library, class dependen akan dimuat oleh classloader yang sama yang tidak memiliki akses ke library dan dependensi lain.
sumber
Anda dapat menggunakan
URLClassLoader
for untuk memuat kelas dari versi diff-2 jars:sumber