Tersine çevirmeyin, bu makale kesinlikle size java sınıflarının yükleme mekanizmasını derinlemesine anlamanızı sağlar.

Önsöz

Java'nın sınıf yükleme mekanizmasını gerçekten anlıyor musunuz? Yazıyı tıklayan arkadaşlar da ilk önce çok yaygın bir mülakat sorusu yapabilirler.Eğer yapabiliyorsanız java'nın sınıf yükleme mekanizmasına zaten hakim olmuş ve anlamışsınızdır.Sonuç beklentilerinizin ötesinde ise gelmek gerekir. Java'nın sınıf yükleme mekanizmasını anlayın. kod aşağıdaki gibi gösterilir

paket com.jvm.classloader;

class Father2 {

public static String strFather = "HelloJVM_Father";

statik{

System.out.println ("Baba statik kod bloğu");

}

}

sınıf Son2, Father2 {

public static String strSon = "HelloJVM_Son";

statik{

System.out.println ("Son statik kod bloğu");

}

}

public class InitativeUseTest2 {

public static void main (String args) {

System.out.println (Son2.strSon);

}

}

operasyon sonucu:

Baba statik kod bloğu

Son statik kod bloğu

MerhabaJVM_Son

Huh? Aslında yukarıdaki prosedür anahtar değil, hepiniz için zor olmayabilir.Neden aşağıdaki mülakat sorusunu yapmıyorsunuz? Aşağıdaki mülakat sorularının hepsi doğru yapılırsa, bu doğru, gerçekten bu makaleyi okumanıza gerek yok.

paket com.jvm.classloader;

class YeYe {

statik {

System.out.println ("YeYe statik kod bloğu");

}

}

class Father, YeYe'yi uzatır {

public static String strFather = "HelloJVM_Father";

statik{

System.out.println ("Baba statik kod bloğu");

}

}

sınıf Oğul Babayı uzatır {

public static String strSon = "HelloJVM_Son";

statik{

System.out.println ("Son statik kod bloğu");

}

}

public class InitiativeUse {

public static void main (String args) {

System.out.println (Son.strFather);

}

Operasyonun sonucunun ne olduğunu tahmin etmek için "hayatınızda öğrenilen" ifadesini kullanalım ...

Dikkat...

operasyon sonucu:

YeYe statik kod bloğu

Baba statik kod bloğu

MerhabaJVM_Father

Zaten çok sayıda doğru ya da yanlış var, düşüncelerinizi açıklamayacağım ...

Yukarıdaki mülakat soruları aslında tipik java sınıfı yükleme problemleridir.Java yükleme mekanizmasını anlamadıysanız, yukarıdaki iki soruda yanılıyor olabilirsiniz. Bu makale Java sınıf yükleme mekanizmasını açıklayacak, böylece Java sınıf yükleme mekanizmasını anlamada yetkin olacaksınız.

Aslında, blog yazarı hala bir soru sormak istiyor. Sonuçta, ilk iki soru için zaten temeliniz var, bu yüzden lütfen koda bakın:

paket com.jvm.classloader;

class YeYe {

statik {

System.out.println ("YeYe statik kod bloğu");

}

}

class Father, YeYe'yi uzatır {

public final static String strFather = "MerhabaJVM_Father";

statik{

System.out.println ("Baba statik kod bloğu");

}

}

sınıf Oğul Babayı uzatır {

public static String strSon = "HelloJVM_Son";

statik{

System.out.println ("Son statik kod bloğu");

}

}

public class InitiativeUse {

public static void main (String args) {

System.out.println (Son.strFather);

}

}

Çok dikkat

İşlem sonucu: HelloJVM_Father

Dürtüsel küçük beyaz ayakkabılar operasyonun sonuçlarını gördü ve blog hesabını kararlı bir şekilde iptal etti ...

1. Sınıf yükleme nedir

JVM'nin önemli bir alanı: sınıf yükleme

Ve sınıf yükleme, sınıf yükleyiciyi içermelidir, önce sınıfın yüklenmesini anlayalım.

Sınıf yükleme:

1. Java kodunda, türün yükleme, bağlantı ve başlatma işlemlerinin tümü, programın çalışması sırasında tamamlanır (sınıfı diskten belleğe yüklemenin üç aşaması) [Unutmayın]

2. Daha fazla esneklik sağlar ve daha fazla olasılığı artırır

Yukarıdaki ilk cümle çok kısa olmasına rağmen, içerdiği bilgi miktarı çok büyük! İki önemli kavram içerir:

1. Tür

Tanımlanan sınıf, arabirim veya numaralandırma tür olarak adlandırılır ve nesneyi içermez.Sınıf yükleme sürecinde, nesne oluşturulmadan önceki bazı bilgilerdir.

2. Programın çalışması sırasında

Program yürütme sırasında tipik bir tamamlama örneği dinamik proxy'dir. Aslında, birçok dil derleme sırasında yüklenir.Java programları tam da bu özellik nedeniyle daha fazla esneklik sağlar ve daha fazla olasılık artırır.

Sınıf yükleme, class.class dosyasındaki ikili verilerin belleğe okunması, çalışma zamanı veri alanının yöntem alanına yerleştirilmesi ve ardından yığın alanında bir java.lang.Class nesnesi oluşturulması anlamına gelir (JVM belirtimi Class nesnesinin nerede bulunduğu belirtilmemiştir. HotSpot sanal makinesi, sınıfın veri yapısını yöntem alanında kapsüllemek için onu yöntem alanına koyar. Sınıf yüklemesinin son ürünü, yığın alanında bulunan Class nesnesidir.Sınıf nesnesi, sınıfın veri yapısını yöntem alanında kapsüller ve Java programcılarına yöntem alanındaki veri yapısına erişmek için bir arabirim sağlar.

Sınıf nesneleri, yöntem alanında değil, yığın alanında depolanır; bu, birçok insanın hata yapması için kolaydır. Sınıf meta verileri, yöntem alanıdır. [Meta veriler, bir sınıfın Sınıf nesnesi değildir. Class nesnesi, yüklenen son üründür, sınıfın yöntem kodu, değişken adları, yöntem adları, erişim hakları, dönüş değerleri vb. Hepsi yöntem alanındadır]

JDK7 tarafından oluşturulan Sınıf örneği yığın içinde saklanır; çünkü JDK7'deki JavaObjectsInPerm parametresinin değeri false olarak sabitlenmiştir.

JDK8 kalıcı nesli kaldırır ve bunun yerine yöntem alanını uygulamak için meta alanı kullanır. Oluşturulan Sınıf örneği hala java yığınında (yığın)

Yeni bir java sınıfı yazarken, JVM onu bir sınıf nesnesi olarak derlememize ve aynı adla .class dosyasında saklamamıza yardımcı olacaktır. Çalışma zamanında, bu sınıftaki bir nesnenin oluşturulması gerektiğinde, JVM bu sınıfın belleğe yüklenip yüklenmediğini kontrol edecektir. Yüklenmemişse, .class dosyasını belleğe yükleyin. Yüklenirse, sınıf dosyasına göre bir örnek nesne oluşturulur.

Class nesnesi ile yeni nesne arasındaki ilişki nasıl anlaşılır?

Yeni nesneye örnek olarak arabayı alın. Araba sınıfı belirli bir kişi olarak kabul edilebilirken, yeni araba bir karakter görüntüsü, belirli bir kişi (Sınıf) benzersizdir ve çoklu karakter görüntüleri (yeni araba) vardır. Aynadaki her karakter görüntüsü belirli bir kişiye göre oluşturulur, yani her yeni nesneye bir şablon olarak Class sınıfı ile başvurulur! Neden ona başvurabilirim? Class nesnesi, yöntem alanındaki veri yapısına erişmek için bir arayüz sağladığından, yukarıda bahsetmiştim!

Unut gitsin, anlamak için aşağıdaki resme bakın, anlamak ikinci, mesele şu ki bu kız oldukça güzel.

Toplam Düğüm:

Sınıfın yüklenmesi basitçe:

.class dosyası (ikili veri) > Belleğe oku > Verileri yöntem alanına koyun > Yığın içinde karşılık gelen Sınıf nesnesini oluşturun > Ve yöntem alanına erişmek için bir arayüz sağlayın

1. Sınıf yüklemesi için notlar

1. Sınıf yükleyicinin, yüklemeden önce belirli bir sınıfın "ilk kez aktif olarak kullanılmasını" beklemesi gerekmez.İlk aktif kullanımın önemli kavramı aşağıda açıklanacaktır.

2. JVM spesifikasyonu, sınıf yükleyicinin, kullanılacağını tahmin ettiğinde bir sınıfı önceden yüklemesine izin verir

3. .class dosyası eksikse veya ön yükleme işlemi sırasında bir hata varsa, sınıf yükleyici, program sınıfı ilk kez aktif olarak kullandığında hatayı (LinkageError hatası) bildirmelidir.Sınıf, program tarafından aktif olarak kullanılmadıysa, o zaman sınıf Yükleyici, hataları bildirmez.

4. Sınıf yüklemesinin son ürünü, yığın alanında bulunan Sınıf nesnesidir

1. 2. .calss dosyası nasıl yüklenir

(1) Doğrudan yerel sistemden yükleyin

(2) .class dosyasını İnternet üzerinden indirin

(3) .class dosyalarını zip ve jar gibi arşiv dosyalarından yükleyin

(4) .class dosyasını ayrılmış veri tabanından çıkarın

(5) Java kaynak dosyalarını dinamik olarak .class dosyalarına derleyin

Her şeyden önce size bir şans vereceğim: JVM'yi bilmeyen çocuk ayakkabıları çok garip görünebilir ve bu duygu tamamen teoriktir.Kavramsal bir izlenim edindiğiniz sürece her kelimenin "ölü bakışı" nı zorlamayın! Sonuçta, öğrenme aşamalı bir süreçtir.

2. Sınıf yaşam döngüsü

Yukarıdaki şekilden de görülebileceği gibi, bir sınıfın sanal makinenin belleğine yüklenmesinden bellekten boşaltmaya kadar olan tüm yaşam döngüsü 7 aşama içerir ve 3 doğrulama, hazırlık ve analiz aşaması topluca bağlantı olarak adlandırılır.

Beş yükleme, doğrulama, hazırlık, başlatma ve boşaltma aşamasının sırası sabitlenir ve belirlenir. Sınıfın yükleme işlemi bu sırayla başlamalıdır ("ilerleme" değil, "başlangıç" olduğunu unutmayın) ve ayrıştırma aşamasının zorunlu olması gerekmez : Bazı durumlarda başlatıldıktan sonra başlatılabilir.Bu, Java dilinin çalışma zamanı bağlamasını desteklemek içindir [yani, java'nın dinamik bağlanması / geç bağlanması].

2. 1. Yükleme

Sınıf yükleme işleminden önceki bölümde ayrıntılı olarak bahsedilmişti. Sınıf yükleme bir .class dosyasıdır (ikili veri) > Belleğe oku > Verileri yöntem alanına koyun > Yığın içinde karşılık gelen Sınıf nesnesini oluşturun > Ve yöntem alanına erişmek için bir arayüz sağlayın

Sınıf yüklemesinin diğer aşamalarıyla karşılaştırıldığında, yükleme aşaması (daha kesin olmak gerekirse, sınıfın ikili bayt akışını elde etme eylemi) en kontrol edilebilir aşamadır, çünkü geliştiriciler sistem tarafından sağlanan sınıf yüklemesini kullanabilir. Yüklemeyi tamamlamak için, yüklemeyi tamamlamak üzere kendi sınıf yükleyicinizi de özelleştirebilirsiniz.

Yükleme aşaması tamamlandıktan sonra, sanal makinenin dışındaki ikili bayt akışı, sanal makinenin gerektirdiği formatta yöntem alanında depolanır ve Java yığınında java.lang.Class sınıfının bir nesnesi de oluşturulur, böylece Nesne erişim yöntemi alanındaki bu veriler.

2, 2. Doğrulama

Doğrulama: yüklenen sınıfın doğruluğunu sağlamak için.

Doğrulama konusunda derinlemesine gitmeye gerek yoktur, ancak sınıf yükleme mekanizmasını anlamak için böyle bir işlem olduğunu ve bu doğrulamanın Sınıf dosyasının bayt akışında bulunan bilgilerin mevcut sanal makinenin gereksinimlerini karşıladığını doğrulamak olduğunu bilmelisiniz.

Dolayısıyla, doğrulama ile ilgili aşağıdaki içerik bir anlayış olarak kullanılabilir!

Doğrulama, bağlantı aşamasının ilk aşamasıdır.Bu aşamanın amacı, Sınıf dosyasının bayt akışında yer alan bilgilerin mevcut sanal makinenin gereksinimlerini karşılamasını ve sanal makinenin güvenliğini tehlikeye atmamasını sağlamaktır. Doğrulama aşaması kabaca 4 aşamalı denetim eylemlerini tamamlayacaktır:

Dosya formatı doğrulaması: bayt akışının Sınıf dosya formatının spesifikasyonlarını karşılayıp karşılamadığını doğrulayın; örneğin: 0xCAFEBABE ile başlayıp başlamadığı, ana ve ikincil sürüm numaralarının mevcut sanal makinenin işlem aralığı içinde olup olmadığı ve sabit havuzdaki sabitlerin desteklenmeyen türlere sahip olup olmadığı .

Meta veri doğrulaması: açıklanan bilgilerin Java dili belirtiminin gereksinimlerini karşıladığından emin olmak için bayt kodu tarafından açıklanan bilgiler üzerinde anlamsal analiz gerçekleştirin (not: anlamsal analizi javac derleme aşamasında karşılaştırın); örneğin: bu sınıfın java dışında bir ana sınıf olup olmadığı .Lang.Object dışında.

Bytecode doğrulama: Veri akışı ve kontrol akışı analizi ile program anlamının yasal ve mantıksal olduğu belirlenir.

Sembol referans doğrulaması: ayrıştırma eyleminin doğru bir şekilde yürütülebilmesini sağlamak için.

Doğrulama aşaması çok önemlidir, ancak gerekli değildir. Programın çalışma zamanı üzerinde hiçbir etkisi yoktur. Başvurulan sınıf tekrar tekrar doğrulandıysa, sanal makine sınıfını kısaltmak için sınıf doğrulama önlemlerinin çoğunu kapatmak için -Xverifynone parametresini kullanmayı düşünebilirsiniz. Yükleme zamanı.

2. 3. Hazırlık [Önemli Noktalar]

Bayt kodu dosyasının doğrulanması tamamlandığında, JVM sınıf değişkeni için bellek ayırmaya ve onu başlatmaya başlayacaktır. Hazırlık aşaması, sınıf değişkeni için resmi olarak bellek ayırma ve sınıf değişkeninin başlangıç değerini ayarlama aşamasıdır.Bu bellekler, yöntem alanında tahsis edilecektir.

Burada dikkat edilmesi gereken iki kilit nokta vardır, yani bellek ayırma nesnesi ve başlatma türü.

Bellek ayırmanın nesneleri: Anlamak için önce Java'da iki tür değişken olduğunu bilmelisiniz, sınıf değişkenleri ve sınıf üyesi değişkenleri Sınıf değişkenleri statik tarafından değiştirilen değişkenleri ve diğer tüm değişken türleri sınıf üyesi değişkenlerine aittir. Hazırlık aşamasında, JVM yalnızca sınıf değişkenleri için bellek ayırır, ancak sınıf üyesi değişkenleri için ayırmaz. Sınıf üyesi değişkenlerin bellek tahsisi, başlatma aşamasına kadar başlamaz (başlatma aşaması aşağıda tartışılacaktır).

Örneğin: Örneğin, hazırlık aşamasında, aşağıdaki kod yalnızca LeiBianLiang özniteliği için bellek ayırır, ChenYuanBL özniteliği için ayırmaz.

public static int LeiBianLiang = 666;

public String ChenYuanBL = "jvm";

Başlatma türü: Hazırlık aşamasında, JVM sınıf değişkenleri için bellek ayıracak ve bunları başlatacaktır (JVM yalnızca sınıf değişkenleri için bellek ayıracak, ancak sınıf üyesi değişkenleri için ayırmayacaktır. Doğal olarak, sınıf üyesi değişkenleri şu anda başlatılamaz. ). Ancak buradaki başlatma, kullanıcı kodunda başlatılan değeri değil, Java dilindeki veri türünün varsayılan değerini değişkene atamayı ifade eder.

Örneğin, hazırlık aşamasından sonraki aşağıdaki kodda LeiBianLiang'ın değeri 666 yerine 0 olacaktır.

public static int LeiBianLiang = 666;

Dikkat! ! !

Dikkat! ! !

Dikkat! ! !

Ancak bir değişken sabitse (statik son ile değiştirilmişse), o zaman hazırlık aşamasında, özniteliğe kullanıcının istediği değer verilecektir. Örneğin aşağıdaki kodda hazırlık aşamasından sonra ChangLiang değeri 0 yerine 666 olacaktır.

public static final int ChangLiang = 666;

1

Statik finalin doğrudan kopyalanmasının nedeni ve statik değişkenlere java dil türünün varsayılan değeri verilecektir. Aslında, biraz düşündükten sonra çözebiliriz.

İki ifade arasındaki fark, birinin son anahtar kelime değişikliğine sahip olması, diğerinin olmamasıdır. Java'daki son anahtar kelime değişmez anlamına gelir, yani ChangLiang'ın değeri atandığında değişmeyecektir. Değer atandıktan sonra değişmeyeceğinden kullanıcının en baştan istediği değer verilmelidir, böylece son değiştirilen sınıf değişkenine hazırlık aşamasında istenilen değer verilecektir. Final tarafından değiştirilmeyen sınıf değişkenleri, başlatma aşamasında veya çalışma aşamasında değişebilir, bu nedenle onlara hazırlık aşamasında kullanıcının istediği değeri vermeye gerek yoktur.

Nihai ve statik anahtar kelimeler hakkında net bir anlayışa sahip değilseniz, aşağıdaki blog yazarı tarafından derlenen makaleye bakmanız önerilir, umarım size yardımcı olur!

Java'da Statik, final ve Statik finalin çeşitli kullanımları

2, 4. Analiz

Hazırlık aşamasını geçtikten sonra analiz aşamasına girin. Ayrıştırma aşaması, sanal makinenin sabit havuzdaki sembol referanslarını doğrudan referanslarla değiştirdiği bir işlemdir.Ayrıştırma eylemleri esas olarak, sınıfların veya arabirimlerin, alanların, sınıf yöntemlerinin, arabirim yöntemlerinin, yöntem türlerinin, yöntem tutamaçlarının ve çağrı noktası niteleyicilerinin 7 tür simge referansı üzerinde gerçekleştirilir. Sembol referansı, hedefi tanımlayan ve herhangi bir değişmez değer olabilen bir dizi semboldür.

Doğrudan referans, doğrudan hedefe işaret eden bir işaretçidir, göreceli bir uzaklık veya hedefe dolaylı olarak yerleştirilmiş bir tutamaçtır.

Aslında, bu aşama bizim için neredeyse şeffaftır, bu yüzden sadece anlayın.

2. 5. Başlatma Anahtar noktalar

Başlatma aşamasında, kullanıcı tanımlı Java program kodu gerçekten çalışmaya başlar.

Java programlarında sınıfların kullanımı iki türe ayrılabilir: aktif kullanım ve pasif kullanım. Genel olarak konuşursak, sınıfın ilklendirilmesi yalnızca sınıf aktif olarak ilk kez kullanıldığında meydana gelir.Peki aktif kullanım nedir? Sınıfların aktif kullanımı aşağıdaki altı Anahtar noktayı içerir:

1. Sınıfın yeni bir yolu olan bir örnek oluşturun

2. Belirli bir sınıfın veya arayüzün statik değişkenine erişin veya statik değişkene bir değer atayın (final tarafından değiştirilen her şey aslında daha doğrudur, derleyicinin sonucu sabit havuza koyduğu statik alan hariç)

3. Sınıfın statik yöntemini çağırın

4. Yansıma (Class.forName ("com.gx.yichun") gibi)

5. Belirli bir sınıfın alt sınıfını başlatın, ardından onun ana sınıfı da başlatılacaktır.

6. Java sanal makinesi başlatıldığında başlangıç sınıfı olarak işaretlenen sınıf (JavaTest) ve ilk olarak Main yöntemi olan sınıf başlatılacaktır.

Son olarak, statik alanlar için, yalnızca bu alanı doğrudan tanımlayan sınıfın başlatılacağını unutmayın (statik bir kod bloğu çalıştırın) Bu cümle, en çok kalıtım ve çok biçimlilikte açıktır! Anlamayı kolaylaştırmak için, aşağıdaki örnekler birbiri ardına açıklanacaktır.

2, 6. Kullanım

JVM, başlatma aşamasını tamamladığında, JVM, kullanıcının program kodunu giriş yönteminden yürütmeye başlar. Bu kullanım aşaması sadece onu anlamak içindir.

2, 7. Kaldırma

Kullanıcı program kodu yürütüldüğünde, JVM oluşturulan Sınıf nesnesini yok etmeye başlar ve son olarak çalıştırmadan sorumlu JVM de bellekten çıkar. Bu kaldırma aşaması sadece onu anlamak içindir.

2, 8. Yaşam döngüsünü sonlandırın

Aşağıdaki durumlarda Java sanal makinesi yaşam döngüsünü sona erdirir

1. System.exit () yöntemi yürütülür

2. Program normal şekilde bitiyor

3. Program, yürütme sırasında bir istisna veya hatayla karşılaştı ve anormal şekilde sonlandırıldı

4. Java sanal makine işlemi, işletim sistemindeki bir hata nedeniyle sonlandırıldı

Mülakat sorularını çözün

paket com.jvm.classloader;

class Father2 {

public static String strFather = "HelloJVM_Father";

statik{

System.out.println ("Baba statik kod bloğu");

}

}

sınıf Son2, Father2 {

public static String strSon = "HelloJVM_Son";

statik{

System.out.println ("Son statik kod bloğu");

}

}

public class InitativeUseTest2 {

public static void main (String args) {

System.out.println (Son2.strSon);

}

}

operasyon sonucu:

Baba statik kod bloğu

Son statik kod bloğu

MerhabaJVM_Son

Bu soruya tekrar dönüp baktığımızda, bu çok basittir, çünkü Son2.strSon, Son sınıfının kendi statik yöntemini çağırır ve aktif olarak kullanılır, bu nedenle Son sınıfını başlatacaktır.Ayrıca, kalıtım nedeniyle, sınıf kalıtımının ilkesi bir alt sınıfı başlatmaktır. Önce ana sınıf başlatılacak, bu nedenle ilk önce ana sınıf başlatılacak!

Baştaki ikinci soruya bakın

paket com.jvm.classloader;

class YeYe {

statik {

System.out.println ("YeYe statik kod bloğu");

}

}

class Father, YeYe'yi uzatır {

public static String strFather = "HelloJVM_Father";

statik{

System.out.println ("Baba statik kod bloğu");

}

}

sınıf Oğul Babayı uzatır {

public static String strSon = "HelloJVM_Son";

statik{

System.out.println ("Son statik kod bloğu");

}

}

public class InitiativeUse {

public static void main (String args) {

System.out.println (Son.strFather);

}

}

operasyon sonucu:

YeYe statik kod bloğu

Baba statik kod bloğu

MerhabaJVM_Father

Bu soru biraz dikkat gerektiriyor, ancak bu makaleyi anlarsanız, bu soru da çok basit. Bu soruda nelere dikkat etmeliyim? Son sınıfının başlatılmadığına, yani Son'un statik kod bloğunun çalıştırılmadığına dikkat edin! Buldunuz mu? O halde analiz edelim ...

İlk olarak Son.strFather'a bakın, Son alt sınıfının Father üst sınıfının statik değişkenine strFather'a eriştiğini göreceksiniz. Şu anda, aktif kullanım kavramını özetlerken bahsettiğim özel bir notu hatırlamalısınız: For static Alan, yalnızca bu alanı doğrudan tanımlayan sınıf başlatılacaktır (statik bir kod bloğu yürütür) Bu cümle en çok kalıtım ve çok biçimlilikte açıktır!

Huh, doğru, Son.strFather'daki statik alan, ana sınıf Father'a aittir, yani, bu alanı doğrudan tanımlayan sınıf, ana sınıf Father'dır, bu nedenle System.out.println (Son.strFather); Bu kod, Son! Alt sınıfı yerine Baba sınıfını başlatacaktır! Hepsini birden anladın mı? Anlıyorsanız, lütfen blog yazarını destekleyin ve beğeni verin, teşekkür ederim ~

Baştaki üçüncü soruya bakın

paket com.jvm.classloader;

class YeYe {

statik {

System.out.println ("YeYe statik kod bloğu");

}

}

class Father, YeYe'yi uzatır {

public final static String strFather = "MerhabaJVM_Father";

statik{

System.out.println ("Baba statik kod bloğu");

}

}

sınıf Oğul Babayı uzatır {

public static String strSon = "HelloJVM_Son";

statik{

System.out.println ("Son statik kod bloğu");

}

}

public class InitiativeUse {

public static void main (String args) {

System.out.println (Son.strFather);

}

}

İşlem sonucu: HelloJVM_Father

Bu sorunun tek özelliği nihai statiktir! Evet, Son.strFather'a karşılık gelen değişken son statik değiştirilmiştir ve hala bu makalede özetlenen sınıfın etkin kullanım kategorisinin ikinci noktasındadır: belirli bir sınıfın veya arabirimin statik değişkenine veya statik değişkene erişim Atama (sonucun derleyici tarafından sabit havuza koyulduğu statik alanlar hariç)

Bu nedenle, bu soru, elbette Main metodunun bulunduğu sınıf dışında hiçbir sınıfı başlatmaz! Bu yüzden sadece System.out.println (Son.strFather) 'ı çalıştırdım; bu yüzden sadece Son.strFather HelloJVM_Father alan sonucunu yazdırdım, ha, anladın mı? Anlıyorsanız, lütfen blog yazarını destekleyin ve beğeni verin, teşekkür ederim ~

Aslında yukarıdaki konu, bu makalede özetlenen kategorilerin aktif kullanım kategorisinin ikinci noktasını tam olarak açıklamıyor! Bunu nasıl söylersin? Nasıl anlaşılır? Daha net hale getirmek için başka bir program yapalım

paket com.jvm.classloader;

ithal sun.applet.Main;

java.util.Random içe aktarın;

java.util.UUID'yi içe aktarın;

class Test {

statik {

System.out.println ("statik statik kod bloğu");

}

// public static final String str = UUID.randomUUID (). toString ();

public static final double str = Math.random (); // Derleme sırasında belirsiz

}

public class FinalUidTest {

public static void main (String args) {

System.out.println (Test.str);

}

}

Sadece sonucu hayal edin Statik kod bloğundaki içerik çalıştırılacak mı?

İşte nokta geliyor

operasyon sonucu

statik statik kod bloğu

0,7338688977344875

Yukarıdaki program, bu makalede özetlenen kategorinin aktif kullanım kategorisinin ikinci noktasındaki cümleyi tamamen göstermektedir: final tarafından değiştirilen herhangi bir şey aslında daha doğru değildir, sonucu derleyicideki sabit havuzun statik alanına koymak daha doğrudur. dışında!

Analiz: Aslında son nokta değil, önemli olan derleyicinin sonucu sabit havuza koymasıdır! Derleme zamanında bir sabitin değeri belirlenmediğinde, bu değer çağıran sınıfın sabit havuzuna yerleştirilmeyecektir.Bu anda program çalışırken, sabitin sınıfının aktif olarak kullanılmasına neden olacaktır, bu nedenle bu sınıf olacaktır başlatma

Bu noktaya kadar, yukarıdaki üç soruyu anlamak iyidir, ancak javayı daha iyi öğrenmek istiyorsanız, blog yazarı size başka bir beyin yakma ziyafeti vermelidir. O, çok hırslı değildir, ancak sadece sizi java ile boğmak istiyor. Kodun kavranması elbette, umarım büyük adamlar hahaha'ya doğrudan kodun üzerine dokunurlar:

paket com.jvm.classloader;

public class ClassAndObjectLnitialize {

public static void main (String args) {

System.out.println ("Baskı bildirimi çıktısı");

}

public ClassAndObjectLnitialize () {

System.out.println ("Yapım Yöntemi");

System.out.println ("Ben bir ayı çocuğuyum, IQ'm =" + ZhiShang + ", EQ =" + QingShang);

}

{

System.out.println ("Ortak Kod Bloğu");

}

int ZhiShang = 250;

statik int QingShang = 666;

statik

{

System.out.println ("statik kod bloğu");

}

}

Bu soru üzerine çok fazla düşünmemeniz tavsiye edilir, aksi takdirde sonuçları okuduktan sonra çok düşündüğünüzü fark edersiniz, bu da sonuçları görmenize ve bilgisayarı parçalamak istemenize neden olabilir hahaha

Çalışan sonuçları profesyonelce ayırın ...

Çalışan sonuçları profesyonelce ayırın ...

Çalışan sonuçları profesyonelce ayırın ...

Çalışan sonuçları profesyonelce ayırın ...

Çalışan sonuçları profesyonelce ayırın ...

operasyon sonucu

Statik kod bloğu

Çıktı yazdırma bildirimi

Buna ne dersin, düşündüğün kadar karmaşık değil mi?

Kısaca inceleyelim.İlk olarak, yukarıda bahsedilen tetikleme başlatmanın altıncı noktasına (aktif kullanım) göre: Java sanal makinesi başlatıldığında başlangıç sınıfı olarak işaretlenen sınıf (JavaTest) ve Main metodu olan sınıf ilk olacaktır. Başlatıldı

Huh? Küçük beyaz çocuk ayakkabılarının soruları var: Ana yöntemlerle sınıfların başlatılacağını söylememiş miydi? Öyleyse neden bu kadar çok şey uygulanmıyor?

Öyleyse sınıfın ilklendirme sırası nedir? Kodumuzda sadece bir yapım metodu olduğunu biliyoruz, ancak aslında Java kodu bayt kodu olarak derlendikten sonra başlangıçta bir inşa metodu kavramı yok, sadece sınıf başlatma metodu ve nesne başlatma metodu.

Şu anda derinlemesine anlamalıyız! Peki bu iki yöntem nasıl ortaya çıktı?

Sınıf başlatma yöntemi: Derleyici, sınıf değişkenlerinin (statik değişkenler), statik kod bloklarının atama ifadelerini toplayacak ve son olarak, görünüm sırasına göre sınıf başlatma yöntemini oluşturacaktır. Sınıf başlatma yöntemi genellikle sınıf başlatıldığında yürütülür.

Dolayısıyla, yukarıdaki örnekte, sınıf başlatma yöntemi aşağıdaki kodu yürütecektir:

static int QingShang = 666; // Sınıf değişkeninin atama ifadesi (statik değişken)

statik // Statik kod bloğu

{

System.out.println ("statik kod bloğu");

}

Sıradan atama ifadelerini ve sıradan kod bloklarını yürütmek yerine

Nesne başlatma yöntemi: görünüm sırasına göre derleyici şunları toplar: üye değişkenlerin atama ifadeleri, sıradan kod blokları ve son olarak yapıcı işlevinin kodunu toplar ve son olarak nesne başlatma yöntemini oluşturur.Yapının izlenmesi veya toplanması yoksa özellikle dikkat etmeye değer İşlev kodu, nesne başlatma yöntemi çalıştırılmayacak. Nesne başlatma yöntemi, genellikle sınıf nesnesi somutlaştırıldığında yürütülür.

Yukarıdaki örnekte, nesne başlatma yöntemi aşağıdaki koddur:

{

System.out.println ("Ortak kod bloğu"); // Ortak kod bloğu

}

int ZhiShang = 250; // Üye değişkenin atama ifadesi

System.out.println ("İnşaat yöntemi"); // Son olarak kurucunun kodunu toplayın

System.out.println ("Ben bir ayı çocuğuyum, IQ'm =" + ZhiShang + ", EQ =" + QingShang);

Sınıf başlatma yöntemini ve nesne başlatma yöntemini anladıktan sonra, yukarıdaki örneğe tekrar bakalım! Evet! Yukarıda bahsedildiği gibi: yapıcı kodu izlenmezse veya toplanmazsa, nesne başlatma yöntemi yürütülmeyecektir. Yukarıdaki örnek, nesne başlatma yöntemini uygulamaz. Unuttun? ClassAndObjectLnitialize sınıfını hiç başlatmadık! Sadece bir çıktı cümlesi yazdım.

Bunu somutlaştırır ve doğrularsak, kod aşağıdaki gibidir:

paket com.jvm.classloader;

public class ClassAndObjectLnitialize {

public static void main (String args) {

new ClassAndObjectLnitialize ();

System.out.println ("Baskı bildirimi çıktısı");

}

public ClassAndObjectLnitialize () {

System.out.println ("Yapım Yöntemi");

System.out.println ("Ben bir ayı çocuğuyum, IQ'm =" + ZhiShang + ", EQ =" + QingShang);

}

{

System.out.println ("Ortak Kod Bloğu");

}

int ZhiShang = 250;

statik int QingShang = 666;

statik

{

System.out.println ("statik kod bloğu");

}

}

operasyon sonucu:

Statik kod bloğu

Normal kod bloğu

Yapım metodu

Ben bir ayı çocuğuyum, IQ = 250, EQ = 666

Çıktı yazdırma bildirimi

sonuç olarak

Sınıf yükleme, bağlantı ve başlatma:

1. Yükle: sınıfın ikili verilerini bulun ve java sanal makinesine yükleyin

2. Bağlantı:

Doğrulama: yüklenen sınıfın doğruluğunu sağlamak için

Hazırlık: Sınıfın statik değişkenleri için bellek ayırın ve onu varsayılan değere ilklendirin, ancak sınıf değişkeni, başlatmadan önce gerçek başlangıç değerine başlatılmaz (eğer son değiştirilmiş bir sınıf değişkeni ise, doğrudan kullanıcının isteğine göre başlatılacaktır. İstenen değer.)

Çözünürlük: Sınıflardaki sembolik referansları doğrudan referanslara dönüştürmek, türün sabit havuzundaki sınıfların, arabirimlerin, alanların ve yöntemlerin sembolik referanslarını arama ve bu sembolik referansları doğrudan referanslarla değiştirme işlemidir.

3. Başlatma: Sınıfın statik değişkenlerine doğru başlangıç değerlerini atayın

Sınıf, beş aşamadan geçmek için diskten belleğe yüklenir: yükleme, bağlama, başlatma, kullanma, boşaltma

Java programları sınıfları iki şekilde kullanır

(1) Aktif kullanım

(2) Pasif kullanım

Tüm Java sanal makine uygulamaları, her sınıf veya arabirim bir Java programı tarafından "ilk kez aktif olarak kullanıldığında" bunları başlatmalıdır.

Aktif kullanım

(1) Sınıfın bir örneğini oluşturun

(2) Belirli bir sınıfın veya arayüzün getstatic statik değişkenine (anımsatıcı) erişin veya statik değişken putstatic atayın

(3) invokestatic sınıfının statik yöntemini çağırın

(4) Yansıma (Class.forName ("com.test.Test"))

(5) Bir sınıfın alt sınıfını başlatın

(6) Java sanal makinesi başlatıldığında başlangıç sınıfı olarak işaretlenen sınıf ve Main yöntemini içeren sınıf

(7) JDK1.7 tarafından sağlanan dinamik dil desteği (anlayın)

Pasif kullanım

Yukarıdaki yedi duruma ek olarak, java sınıflarını kullanmanın diğer yöntemleri, sınıfların pasif kullanımı olarak kabul edilir ve sınıf başlatmaya yol açmaz.

çok dikkat

Giriş yöntemini başlatın. Sınıf yüklemesinin başlatma aşamasına girerken, JVM, ana yöntemin bulunduğu tüm sınıfı başlatmak için tüm ana yöntem girişini arayacaktır. Bir sınıfın başlatılması gerektiğinde, önce sınıf yapıcısını () başlatacak ve sonra nesne yapıcısını () başlatacaktır.

Sınıf yapıcısını başlatın: JVM, sınıf değişkenlerinin atama ifadelerini ve statik kod bloklarını sırayla toplayacak ve son olarak JVM tarafından yürütülecek sınıf yapıcısını oluşturacaktır.

Nesne yapıcısını başlatın: JVM, üye değişken atama deyimlerini, sıradan kod bloklarını toplayacak ve son olarak inşa yöntemlerini toplayacak, bunları bir nesne oluşturucuda oluşturacak ve son olarak JVM tarafından çalıştıracaktır. Yapıcı kodu izlenmezse veya toplanmazsa, nesne başlatma yönteminin çalıştırılmayacağına dikkat etmek önemlidir. Nesne başlatma yöntemi, genellikle sınıf nesnesi somutlaştırıldığında yürütülür.

Ana yöntemin bulunduğu sınıfı başlattığınızda diğer sınıfların başlatılmasıyla karşılaşırsanız, önce ilgili sınıfı yükleyin ve yükledikten sonra geri dönün. Bu döngüyü tekrarlayın ve son olarak ana yöntemin sınıfına dönün.

Tabii ki, bu makale sınıf yükleyici ve ebeveyn yetkilendirme modeli vb. Hakkında konuşmadı, daha sonra özetleyeceğim!

Bu makale size biraz yardımcı oluyorsa, lütfen bana bir başparmak verin, teşekkür ederim ~

Orijinal bağlantı: https://blog.csdn.net/qq_44543508/article/details/102983363

Birdenbire, zorlu araştırma ve geliştirmeden geçen, yerel olarak üretilen işletim sistemi başarısız oldu ve rakip Microsoft değil
önceki
İllüstrasyonÖnümüzdeki 30 yılda Çin nasıl görünecek? Mücadele yol haritası burada ve sizinle yakından ilgili
Sonraki
2019 Chen Bochui Uluslararası Çocuk Edebiyatı Ödülü'nde, Şangay'da doğan iki yaşlı ellerini bir arada tutuyor.
Çok sayıda göçmen kuş kış için Poyang Gölü'ne uçtu
Piton balık kafesine hapsolmuş balığı çalar! Şişkin
On yıllık sıkı çalışma, "Ma Zhuju" ve diğer yıldız ulusal hazineleri Zhejiang Expo'da görücüye çıkacak bir grup oluşturuyor.
2019'un sonu emlak piyasasını avlamak için iyi bir zaman mı?
Patlamak! Güney Kore Savunma Araştırma Enstitüsündeki patlama 1 kişinin ölümüne ve 6 kişinin yaralanmasına neden oldu
15. "Yeniden Canlandırma Kupası" Ulusal Gençlik Mesleki Beceriler Yarışması'nın öğrenci grubu Hangzhou'da başladı
Guangdong, Taishan'da domuz endüstrisindeki değişiklikler
Sıradan insanların satın alması için en güvenli ve en uygun finansal yönetim yöntemi hangisidir?
Yurt dışına çıkmayın, tüm dünyayı görün: National Expo, 8 gün ertelendi, popülerlikle dolu
Hong Kong'da mobil ödemeyi yaygınlaştırmak neden bu kadar zor?
Hepsi bir üniversite yönetmek için Çin'e geliyor! Oxford Cambridge Yale Berkeley Tsinghua Üniversitesi ...
To Top