Derleme süresi ve Çalışma Süresi Bağımlılığı - Java


95

Java'da derleme zamanı ve çalışma zamanı bağımlılıkları arasındaki fark nedir? Sınıf yolu ile ilgilidir, ancak bunlar nasıl farklıdır?

Yanıtlar:


82
  • Derleme zamanı bağımlılığı : Yapınızı derlemek için bağımlılığa ihtiyacınız var CLASSPATH. Bunlar, kodunuzda sabit kodlanmış bağımlılık için bir tür "referansa" sahip olduğunuz için üretilir; örneğin, newbir sınıfı çağırmak , bir şeyi genişletmek veya uygulamak (doğrudan veya dolaylı olarak) veya doğrudan reference.method()gösterimi kullanan bir yöntem çağrısı gibi .

  • Çalışma zamanı bağımlılığı : CLASSPATHYapınızı çalıştırmak için kendi bağımlılığınıza ihtiyacınız var . Bağımlılığa erişen kodu yürüttüğünüz için üretilirler (ya kodlanmış bir şekilde ya da yansıtma yoluyla ya da her neyse).

Derleme zamanı bağımlılığı genellikle çalışma zamanı bağımlılığı anlamına gelse de, yalnızca derleme zamanı bağımlılığınız olabilir. Bu, Java'nın yalnızca sınıf bağımlılıklarını o sınıfa ilk erişime bağladığı gerçeğine dayanmaktadır; bu nedenle, bir kod yolu hiçbir zaman geçilmediği için çalışma zamanında belirli bir sınıfa asla erişmezseniz, Java hem sınıfı hem de bağımlılıklarını göz ardı eder.

Bunun örneği

C. java'da (C.class oluşturur):

package dependencies;
public class C { }

A. java'da (A. sınıfını üretir):

package dependencies;
public class A {
    public static class B {
        public String toString() {
            C c = new C();
            return c.toString();
        }
    }
    public static void main(String[] args) {
        if (args.length > 0) {
            B b = new B();
            System.out.println(b.toString());
        }
    }
}

Bu durumda, Abir derleme zamanı bağımlılığı olan Cthrough B, ancak yürütme bazı parametreleri geçmesi durumunda sadece C üzerinde çalışma zamanı bağımlılığı olacak java dependencies.AJVM sadece çözmeye çalışacağı gibi Bhakkında yaptığı bağımlılığını Co yürütmek için aldığında B b = new B(). Bu özellik, çalışma zamanında yalnızca kod yollarınızda kullandığınız sınıfların bağımlılıklarını sağlamanıza ve yapıdaki diğer sınıfların bağımlılıklarını yok saymanıza olanak tanır.


1
Bunun artık çok eski bir cevap olduğunu biliyorum, ancak JVM başlangıçtan itibaren çalışma zamanı bağımlılığı olarak C'ye nasıl sahip olamaz? "İşte C'ye bir referans, onu bağımlılık olarak ekleme zamanı" tanıyabiliyorsa, o zaman C zaten bir bağımlılık değil mi, çünkü JVM onu tanıyor ve nerede olduğunu biliyor mu?
wearebob

@wearebob Tahminimce bu şekilde belirtilebilirdi, ancak tembel bağlantının daha iyi olduğuna karar verdiler ve kişisel olarak yukarıda belirtilen nedenden dolayı kabul ediyorum: gerekirse bazı kodlar kullanmanıza izin verir, ancak sizi onu dahil etmeye zorlamaz ihtiyacınız yoksa dağıtımınız. Bu, üçüncü taraf kodlarıyla uğraşırken oldukça kullanışlıdır.
gpeche

Yine de bir yere yerleştirilmiş bir kavanozum varsa, zaten tüm bağımlılıklarını içermesi gerekecek. Bağımsız değişkenlerle çalıştırılıp çalıştırılmayacağını bilmez (bu nedenle C'nin kullanılıp kullanılmayacağını bilmez), bu nedenle C'nin her iki şekilde de kullanılabilir olması gerekir. Başlangıçtan itibaren sınıf yolunda C bulunmayarak herhangi bir bellek / zamanın nasıl kaydedildiğini anlamıyorum.
wearebob

1
@wearebob bir JAR'ın tüm bağımlılıklarını içermesi gerekmez. Bu nedenle, önemsiz olmayan hemen hemen her uygulamanın bir / lib dizini veya birden çok JAR içeren benzer bir dizini vardır.
gpeche

34

Kolay bir örnek, servlet api gibi bir api'ye bakmaktır. Sunucu uygulamalarınızın derlenmesini sağlamak için, servlet-api.jar dosyasına ihtiyacınız vardır, ancak çalışma zamanında servlet kapsayıcısı bir servlet api uygulaması sağlar, böylece çalışma zamanı sınıf yolunuza servlet-api.jar eklemeniz gerekmez.


Açıklık getirmek gerekirse (bu beni şaşırttı), eğer maven kullanıyor ve bir savaş inşa ediyorsanız, "servlet-api" genellikle bir "çalışma zamanı" bağımlılığı yerine "sağlanan" bir bağımlılıktır ve bu, eğer Ben doğruyum.
xdhmoore

2
'sağlanan', derleme zamanında dahil anlamına gelir, ancak onu WAR veya diğer bağımlılıklar koleksiyonunda paketlemeyin. 'runtime' tersini yapar (derlemede mevcut değildir, ancak WAR ile paketlenmiştir).
KC Baltz 04

30

Derleyicinin bir kitaplığa çağrıları derlemek için doğru sınıf yoluna ihtiyacı vardır (derleme zamanı bağımlılıkları)

JVM, çağırdığınız kitaplıktaki sınıfları yüklemek için doğru sınıf yoluna ihtiyaç duyar (çalışma zamanı bağımlılıkları).

Birkaç yönden farklı olabilirler:

1) C1 sınıfınız L1 kitaplık sınıfını ve L1 kitaplık sınıfını L2'yi çağırırsa, C1'in L1 ve L2'ye bir çalışma zamanı bağımlılığı vardır, ancak L1'e yalnızca derleme süresi bağımlılığı vardır.

2) C1 sınıfınız Class.forName () veya başka bir mekanizma kullanarak bir I1 arabirimini dinamik olarak başlatırsa ve arabirim I1 için uygulama sınıfı sınıf L1 ise, C1'in I1 ve L1'e bir çalışma zamanı bağımlılığı vardır, ancak yalnızca bir derleme zamanı bağımlılığı vardır. I1'de.

Derleme zamanı ve çalışma zamanı için aynı olan diğer "dolaylı" bağımlılıklar:

3) C1 sınıfınız L1 kitaplık sınıfını genişletir ve L1, I1 arabirimini uygular ve kitaplık sınıfı L2'yi genişletir: C1, L1, L2 ve I1'e derleme zamanı bağımlılığına sahiptir.

4) C1 sınıfınızın bir yöntemi foo(I1 i1)ve bar(L1 l1)I1'in bir arabirim olduğu ve L1'in I1 arabirimi olan bir parametre alan bir sınıf olduğu bir yöntem vardır: C1, I1 ve L1'e derleme zamanı bağımlılığına sahiptir.

Temel olarak, ilginç bir şey yapmak için, sınıfınızın sınıf yolundaki diğer sınıflar ve arabirimlerle arayüz oluşturması gerekir. Bu kitaplık arabirimleri kümesi tarafından oluşturulan sınıf / arabirim grafiği , derleme zamanı bağımlılık zincirini verir. Kitaplık uygulamaları , çalışma zamanı bağımlılık zincirini verir. Çalışma zamanı bağımlılık zincirinin çalışma zamanına bağlı veya başarısız-yavaş olduğuna dikkat edin: L1 uygulaması bazen L2 sınıfının bir nesnesinin somutlaştırılmasına bağlıysa ve bu sınıf yalnızca belirli bir senaryoda somutlaştırılırsa, bu durumda aşağıdakiler dışında hiçbir bağımlılık yoktur bu senaryo.


1
Örnek 1'deki derleme zamanı bağımlılığı L1 olmamalı mı?
BalusC

Teşekkürler, ancak çalışma zamanında sınıf yükleme nasıl çalışır? Derleme zamanında anlaşılması kolaydır. Ancak çalışma zamanında, farklı sürümlerde iki Jar'ım olduğu bir durumda bu nasıl davranır? Hangisini seçecek?
Kunal

1
Varsayılan sınıf yükleyicinin sınıf yolunu alıp sırayla geçtiğinden oldukça eminim, bu nedenle sınıf yolunda her ikisi de aynı sınıfı içeren iki kavanozunuz varsa (örn. Com.example.fooutils.Foo), bunu kullanacaktır. sınıf yolunda birinci. Ya öyle ya da belirsizliği belirten bir hata alırsınız. Ancak, sınıf yükleyicilere özel daha fazla bilgi istiyorsanız, ayrı bir soru sormalısınız.
Jason S

Bence ilk durumda, derleme zamanı bağımlılıkları L2'de de olmalıdır, yani cümle: 1) C1 sınıfınız L1 kitaplık sınıfını ve L1 kitaplık sınıfı L2'yi çağırıyorsa, C1'in L1 üzerinde çalışma zamanı bağımlılığı vardır ve L2, ancak yalnızca L1 ve L2'ye derleme süresi bağımlılığı. Bu, derleme zamanında olduğu gibi, java derleyicisi L1'i de doğruladığında, L1 tarafından referans verilen diğer tüm sınıfları da doğrular (Class.forName ("sınıfımadı) gibi dinamik bağımlılıklar hariç) ... aksi takdirde bunu nasıl doğrular? derleme iyi çalışıyor. Lütfen aksini düşünüyorsanız açıklayın
Rajesh Goel

1
Hayır. Derleme ve bağlantının Java'da nasıl çalıştığını okumalısınız. Derleyicinin ilgilendiği tek şey, harici bir sınıfa atıfta bulunduğunda, o sınıfın nasıl kullanılacağıdır , örneğin, yöntemlerinin ve alanlarının ne olduğu. Bu harici sınıfın yöntemlerinde gerçekte ne olduğu umurunda değil. L1 L2'yi çağırırsa, bu L1'in bir uygulama ayrıntısıdır ve L1 zaten başka bir yerde derlenmiştir.
Jason S

13

Java aslında derleme zamanında hiçbir şeyi bağlamaz. Yalnızca CLASSPATH'da bulduğu eşleşen sınıfları kullanarak sözdizimini doğrular. Her şeyin bir araya getirilmesi ve o sırada CLASSPATH'a göre yürütülmesi çalışma zamanına kadar değildir.


Yükleme süresine kadar değil ... çalışma zamanı, yükleme süresinden farklıdır.
2019

11

Derleme zamanı bağımlılıkları yalnızca doğrudan derlediğiniz sınıfta kullandığınız bağımlılıklardır (diğer sınıflar) . Çalışma zamanı bağımlılıkları, çalıştırdığınız sınıfın hem doğrudan hem de dolaylı bağımlılıklarını kapsar. Bu nedenle, çalışma zamanı bağımlılıkları, bağımlılıkların bağımlılıklarını ve a'da sahip olduğunuz String, ancak içinde kullanılan sınıf adları gibi yansıma bağımlılıklarını içerir Class#forName().


Teşekkürler, ancak çalışma zamanında sınıf yükleme nasıl çalışır? Derleme zamanında anlaşılması kolaydır. Ancak çalışma zamanında, farklı sürümlerde iki Jar'ım olduğu bir durumda bu nasıl davranır? Bir sınıf yolunda farklı sınıflardan birden çok sınıf olması durumunda Class.forName () hangi sınıfı alır?
Kunal

Tabii ki adla eşleşen. Eğer varsa aslında "aynı sınıfta birden fazla sürümünü" demek, o zaman classloader bağlıdır. "En yakın" olan yüklenecektir.
BalusC

Bence A.jar ile A, B.jar ile B extends Ave C.jar ile birlikte varsa, C extends Bo zaman C.jar, A'ya C bağımlılığı dolaylı olsa da, A.jar üzerinde derleme süresine bağlıdır.
gpeche

1
Tüm derleme zamanı bağımlılıklarındaki sorun, arabirim bağımlılığıdır (arabirim bir sınıfın yöntemleri aracılığıyla veya bir arabirimin yöntemleri aracılığıyla veya bir sınıf veya arabirim olan bir argüman içeren bir yöntem aracılığıyla)
Jason S

2

Java için derleme zamanı bağımlılığı, kaynak kodunuzun bağımlılığıdır. Örneğin, A sınıfı B sınıfından bir yöntemi çağırırsa, derleme zamanında A B'ye bağımlıdır, çünkü A'nın derlenecek B'yi (B türü) bilmesi gerekir. Buradaki hile şu olmalıdır: Derlenmiş kod henüz tam ve çalıştırılabilir bir kod değildir. Henüz derlenmemiş veya harici kavanozlarda mevcut olmayan kaynaklar için değiştirilebilir adresler (semboller, meta veriler) içerir. Bağlanma sırasında, bu adresler bellekteki gerçek adreslerle değiştirilmelidir. Bunu düzgün yapmak için doğru semboller / adresler oluşturulmalıdır. Ve bu (B) sınıfının türü ile yapılabilir. Derleme zamanındaki ana bağımlılığın bu olduğuna inanıyorum.

Çalışma zamanı bağımlılığı daha çok gerçek kontrol akışıyla ilgilidir. Gerçek hafıza adreslerini çağırır. Programınız çalışırken sahip olduğunuz bir bağımlılıktır. Burada yalnızca tür bilgileri değil, uygulamalar gibi B sınıfı ayrıntılara da ihtiyacınız var. Sınıf mevcut değilse, RuntimeException alırsınız ve JVM çıkar.

Her iki bağımlılık da, genellikle ve olmamalıdır, aynı yönde akar. Bu bir OO tasarım meselesidir.

C ++ 'da, derleme biraz farklıdır (tam zamanında değil) ancak bir bağlayıcı da vardır. Yani süreç sanırım Java'ya benzer düşünülebilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.