2012-07-18 35 views
17

Oralarda üzerinde ne Java classloaders 10 milyon makale ve belgeler, ve /* neden * Kendi yazmayı ... ama hepsi Basit bulamadığını bazı şeyleri varsayarak gibi görünüyor cevaplamak!Java sınıfı yükleyiciler ne zaman devreye girer?

Sınıf yükleyicinin işini anlıyorum: bayt kodunu okumak ve ondan bir nesne oluşturmak. Farklı classloaders vb farklı bunu

Fakat kendi kodunda bir sınıf yükleyici API karşı koduna olmayan, daha önce, ben anlamakta büyük zorluk yaşıyorum Benim de bir yazmak zorunda asla sahip bir ClassLoader ' kendi kodu aslında patlar. Örneğin

: Burada

public static void main(String[] args) { 
    Fizz fizz = new Fizz(); 
    fuzz.buzz(); 
} 

, bir Fizz nesne var. Fizz modelinin başlatılabilmesi için, Fizz.class ürününü önbelleğe yüklemek ve yüklemek için bir sınıf yükleyiciye ihtiyacımız var. Bu nerede ve ne zaman gerçekleşiyor?!?! Açıkça benim kodumda değil, dolaylı olarak JRE'de bir yerde olmalı mı? Ben kendi classloader yazarsanız bu soruya Teğet

, WidgetClassLoader derler ve o da benim uygulamanın sınıflarını yüklemek, ya da belki sadece benim Fizz.class, benim uygulamasına bu WidgetClassLoader "kravat" nasıl bu kadar biçimde yapılandırmak istediğiniz Hangi classloader kullanacağını biliyor mu? Kodumun bu classloader'ı açıkça çağırması mı gerekiyor yoksa ilk örnek gibi gizli mi olurdu? Şimdiden teşekkürler!

+0

Elbette, JRE'de. Bunu okuyun ve Google özel sınıf yükleyici yapılandırması için: http://www.javalobby.org/java/forums/t18345.html – duffymo

+0

@duffymo - lütfen Andre'nin cevabı altında yaptığım yorumu görün - Seninle aynı sorum var! – IAmYourFaja

+0

Hiç kendi başına bir sınıf yükleyici yazmanın gerekliliğini görmüyorum. Bir keresinde değil, tüm zaman boyunca Java yazıyordum. Ve bu 1997'den beri geri döndü. 1997'ye ihtiyacınız olduğunu düşündüren nedir? – duffymo

cevap

6

Sorunuz şu anda düşündüğünüz kadar önemsiz değil.

Fizz örneğiniz: Fizz ne zaman yüklenir? Bu, JLS (Chapter 5.4: Linking)'da tanımlanmıştır. Fizz'in ne zaman yükleneceğini tanımlamaz, ancak görünür davranışı garanti eder. 'Ne zaman' bölümü için, Fizz bulunamazsa, Fizz'e (Fizz fizz = new Fizz()) erişen ilk ifadeden bir istisna atılacaktır. Eminim ki bu durumda özellikle yeni Fizz() olacaktır, çünkü öncelikle ifadenin sağ tarafı değerlendirilir.Eğer bunu böyle yazmıştı:

Bu durumda
Fizz fizz = null; 
fizz = new Fizz(); 

Fizz fizz = null zaten İstisna atardı çünkü Fizz sınıfına ilk erişim.

Fizz yüklüyor? Bir sınıfın yüklenmesi gerektiğinde, sınıfı almak için sınıfa gerektiren koda ait 'classloader' kullanılır. Fizz örneğinde, bu, sınıfı ana yöntemle yükleyen classloader olacaktır. Tabii ki, sınıf yükleyici Fizz'i kendi başlarına yükleyemezse ana sınıf yükleyicisine temsilci seçmeyi tercih edebilir.

JVM'yi benim ClassLoader kullanmam için nasıl alabilirim? Açıkça veya örtülü olarak iki yol vardır. Açıkça: Kendi sınıf yükleyiciniz aracılığıyla yöntemlerini çağırarak bir sınıf yükleyebilirsiniz. Kasten: sınıf yükleyicinizden yüklenen bir sınıftan kod (anlam yöntemleri veya başlatıcıları) çalıştırdığınızda ve işlemde bir sınıf başvurusunun çözülmesi gerektiğinde, kodlayıcıyı yükleyen sınıf yükleyicisi olduğundan, sınıf yükleyiciniz otomatik olarak kullanılır. ilk yer.

+0

Bu bana +1 benden emin olmadığım bir parçayı yanıtlıyor :-) –

+0

+1 "my" classLoader öğesinin hiçbir değeri yok Thread.currentThread(). GetContextClassLoader() 'yani her bir Thread'in varsayılan sınıf yükleyicisi var ve Farklı olabilirler. –

+1

@Durandal, Açık ve kapalı yükleme hakkında, Fizz örneğinde, özel sınıf yükleyicinin kullanılmayacağından emin olun .. doğru mu? Temel olarak, Implicit yüklemesi için, bir yerde açıkça yükleme işlemi başlatmalıdır. Burada ya açık bir şekilde yüklenmek için Fizz sınıfı için Class.forName() kullanabilir ya da JVM'nin yükleneceği şekilde sınıf yoluna Fizz sınıfını yerleştirebilir. Sonuç, Özel sınıf yükleyicinin sadece ilk kez açık bir yaklaşımla çalışacağıdır. Eğer Yanlışsam beni düzelt. – AKS

3

Java'nın varsayılan bir sınıfı yükleyici vardır. Bu, varsayılan sınıf yolunda sınıf bildirimlerini arar. Kendi sınıf yükleyicinizi yazarsanız, ana sınıf yükleyiciyi ayarlayabilirsiniz (ve yapmalısınız). Başka bir tane yoksa, bu varsayılan olur. Eğer yuo bunu yapmazsa sınıf yükleyiciniz java API sınıflarını bulamazdı. Java bir sınıf ararsa, size özel sınıf yükleyiciyle değil, ana sınıf yükleyiciyle bakmaya başlamaz. Bu bir ebeveyn varsa, oradan başlar. Sadece bir sınıf bulunamadıysa, bir sonraki çocuk sınıfı yükleyici tekrar denemek için kullanılır. Yine bu, çocuklar olduğu sürece devam eder. Sınıf, zincirdeki herhangi bir yükleyici tarafından bulunmazsa, ClassNotFoundException atılır.

Elbette java, yalnızca sınıf yükleyiciyi varsayılan yükleyici olarak ayarlarsanız (Thread.currentThread().setContextClassLoader() numaralı telefonu arayarak) veya sınıfı manuel olarak (loadClass() numaralı telefonu arayarak) yükler.

Sınıf yükleyicinin ne zaman çalıştırıldığından emin değilim. Programın başlatılmasında (import olarak bildirilen tüm sınıflarda) veya bir sınıfın ilk kullanımında (değişken bildirim veya yapıcı çağrısı) çalıştırıldığını düşünüyorum.

+0

Teşekkürler @Andre, ama bir kez daha, bu soruya bir cevaptır "* Sınıfçılar nasıl çalışır?" * Anlıyorum classloader hiyerarşisi - anlamadığım şey JRE varsayılan sınıf yükleyicinin 'Fizz.class' öğesini oluşturan kodu ne zaman ve nerede yürüttüğüdür. – IAmYourFaja

+0

java.lang'da bir kesme noktası ayarlamayı deneyin.'LoadClass() 'yönteminde ClassLoader'. –

+0

Biraz düşündüm ve cevabımı düzenledim. Üzgünüm ama bu son kısımdan emin değilim. –

0

Sınıfın gerçek oluşturulması defineClass'da gerçekleşir. Sınıf, birkaç kaynaktan herhangi birinden bir bayt dizisi kullanılarak oluşturulur.

normal yollarında (protected olan) (tabii ki, aynı zamanda protected olan) findClass yoluyla defineClass almak. Yani normal giriş noktası loadClass ->findClass ->defineClass. Ama özel durumlar için başka yollar var.

(her şey oldukça dolambaçlı ve koruma daha fazla karmaşık oldu katmanları ekleyerek bir geçmişe ve daha çeşitli erişim modlarını temsil eder.)

Eğer classloaders ilgileniyorsanız
0

ve ve nasıl çalışır , ayrıca the OSGi specification da kontrol edebilirsiniz - bana öyle görünüyor ki sizin için çok ilginç bir okuma olacak. OSGi, modülerliği, açık kod ayırma ve yaşam döngüsü yönetimini sağlayan ve şu anda çok popüler olan Java için bir çerçevedir (örneğin, Eclipse'in kendisi bir esasına dayanmaktadır).

OSGi, sınıf yükleyicilerini yoğun olarak kullanır ve sınıf içi yüklemeler ile ilgili her şeyin özelliklerin içinde nasıl ve ne zaman gerçekleştiğine dair çok güzel bir açıklama vardır. Temel olarak, her bir paket için ayrı bir paket sınıf yükleyicisi vardır (bu modüller nasıl adlandırılır) ve bu sınıf yükleyiciler, bağımlılıkları ve doğru sınıfı diğer gruptan getiriyor.

İlgili konular