Bu orijinal soruyu cevaplamıyor, ancak soru herhangi bir ContextClassLoadersorgu için yüksek dereceli ve bağlantılı olduğundan, bağlam sınıfı yükleyicinin ne zaman kullanılması gerektiği ile ilgili soruyu cevaplamanın önemli olduğunu düşünüyorum. Kısa cevap: asla bağlam sınıfı yükleyiciyi kullanmayın ! Ancak getClass().getClassLoader(), ClassLoaderparametresi eksik bir yöntemi çağırmanız gerektiğinde bunu ayarlayın .
Bir sınıftan kod başka bir sınıf yüklemeyi istediğinde, kullanılacak doğru sınıf yükleyici, arayan sınıfı ile aynı sınıf yükleyicisidir (yani getClass().getClassLoader()). Bu, işlerin% 99.9'unun çalışma biçimidir, çünkü JVM, yeni bir sınıf örneği ilk kez oluşturduğunuzda, statik bir yöntemi çağırdığınızda veya statik bir alana eriştiğinizde budur.
Yansıma kullanarak bir sınıf oluşturmak istediğinizde (örneğin, yapılandırılmış adlandırılmış bir sınıfın serileştirilmesi veya yüklenmesi gibi), yansımayı yapan kitaplık , uygulamadanClassLoader bir parametre olarak alarak her zaman uygulamaya hangi sınıf yükleyicinin kullanılacağını sormalıdır . (İnşa edilmesi gereken tüm sınıfları bilen) uygulama bunu geçmelidir getClass().getClassLoader().
Sınıf yükleyici almanın başka bir yolu yanlıştır. Gibi bir kütüphane kullanımları kesmek durumunda Thread.getContextClassLoader(), sun.misc.VM.latestUserDefinedLoader()ya sun.reflect.Reflection.getCallerClass()da API eksikliğinden kaynaklanan bir hatadır. Temel olarak, Thread.getContextClassLoader()sadece ObjectInputStreamAPI'yi tasarlayan kişi ClassLoaderparametre olarak kabul etmeyi unuttuğu ve bu hata Java topluluğunu bugüne kadar perdelediği için var.
Bununla birlikte, birçok JDK sınıfı, bazı sınıf yükleyicilerin kullanmasını tahmin etmek için birkaç hack'ten birini kullanır. Bazıları ContextClassLoader(paylaşılan bir iş parçacığı havuzunda farklı uygulamalar çalıştırdığınızda veya ayrıldığınızda ContextClassLoader nullbaşarısız olur), bazıları yığını (sınıfın doğrudan arayanı bir kütüphane olduğunda başarısız olur) kullanır, bazıları sistem sınıfı yükleyiciyi kullanır (sadece sınıftaki sınıfları kullanmak için belgelendiği sürece iyidir CLASSPATH) veya bootstrap sınıf yükleyicisi ve bazıları yukarıdaki tekniklerin (yalnızca işleri daha karmaşık hale getirir) öngörülemeyen bir kombinasyonunu kullanır. Bu, dişlerin çok fazla ağlamasına ve gıcırdamasına neden oldu.
Böyle bir API kullanırken, önce sınıf yükleyiciyi parametre olarak kabul eden yöntemin aşırı yüklenmesini bulmaya çalışın . Mantıklı bir yöntem yoksa, ContextClassLoaderAPI çağrısından önce ayarlamayı (ve daha sonra sıfırlamayı) deneyin :
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
// call some API that uses reflection without taking ClassLoader param
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
ClassBsınıf yolunda olması gerektiğini söylüyorsunuz ? Yükleyicisinin sınıf yolunda olmasa bile başarıyla yüklenebilmesi için geçersiz kılınması mümkün değil mi?ClassAClassAClassAloadClass()ClassBClassB