Bu sefer Java bayt kodu dosyalarını iyice anlayın

Yazar | Dongsheng'i Düşünmek

Sorumlu Editör | Elle

Java'nın genel bayt kodu analizi yolculuğuna başlamak için doğrudan Java kaynak kodunun en basit parçasından uzun soluklu değil.

Java kaynak dosyaları

paket com.dskj.jvm.bytecode; public class MyTest1 { private int a = 1; public int getA { dönüş a; } Kamu geçersiz setA (int a) { inci dır-dir .a = a; } }

Java bayt kodu dosyası

IDEA aracı kodu derledikten sonra, Terminal terminal konsolu, sınıf dosyasının oluşturulduğu dizine girin.

Aşağıdaki komutları yürütün:

javap -verbose com.tr .dskj.jvm.bytecode.MyTest1

Bayt kodu dosya içeriği oluşturun:

Sınıf dosyası /.../classes/com/dskj/jvm/bytecode/MyTest.class Son değiştirilme tarihi: 31 Temmuz 2018; boyut 489 bayt MD5 sağlama toplamı bdb537edd2d216ea99d6ce529073ee42 "MyTest1.java" dan derlenmiştir genel sınıf com.dskj.jvm.bytecode.MyTest ikincil versiyon: 0 ana sürüm: 52 # JDK maksimum sürüm numarası bayraklar: ACC_PUBLIC, ACC_SUPER Sabit havuz: # # 1 = Methodref # 4. # 20 // java / dil / Nesne. " < içinde > ": V # 2 = Alan referans # 3. # 21 // com / dskj / jvm / bayt kodu / MyTest1.a: I # 3 = Sınıf # 22 // com / dskj / jvm / bytecode / MyTest1 # 4 = Sınıf # 23 // java / dil / Nesne # 5 = Utf8 a # 6 = Utf8 I # 7 = Utf8 < içinde > # 8 = Utf8 V # 9 = Utf8 Kodu # 10 = Utf8 LineNumberTable # 11 = Utf8 LocalVariableTable # 12 = Uf8 inci dır-dir # 13 = Utf8 Lcom / dskj / jvm / bayt kodu / MyTest1; # 14 = Utf8 getA # 15 = Utf8 I # 16 = Utf8 setA # 17 = Utf8 (I) V # 18 = Utf8 Kaynak Dosyası # 19 = Utf8 MyTest1.java # 20 = NameAndType # 7: # 8 // " < içinde > ": V # 21 = NameAndType # 5: # 6 // a: I # 22 = Utf8 com / dskj / jvm / bayt kodu / MyTest1 # 23 = Utf8 java / lang / Nesne { public com.dskj.jvm.bytecode.MyTest1; tanımlayıcı: V bayraklar: ACC_PUBLIC Kod: stack = 2, locals = 1, args_size = 10: aload_01: özel # 1'i çağırın // Yöntem java / lang / Object. " < içinde > ": V 4: aload_05: iconst_16: putfield # 2 // Alan a: I 9: dönüş LineNumberTable: satır 6: 0 satır 8: 4 LocalVariableTable: Başlangıç Uzunluğu Yuva Adı İmza 0100 th dır-dir Lcom / dskj / jvm / bayt kodu / MyTest1; public int getA; tanımlayıcı: I bayraklar: ACC_PUBLIC Kod: stack = 1, locals = 1, args_size = 10: aload_01: getfield # 2 // Alan a: I 4: ireturn LineNumberTable: satır 11: 0 LocalVariableTable: Başlangıç Uzunluğu Yuva Adı İmza 05 0. dır-dir Lcom / dskj / jvm / bayt kodu / MyTest1; public void setA (int); tanımlayıcı: (I) V bayraklar: ACC_PUBLIC Kod: stack = 2, locals = 2, args_size = 20: aload_01: iload_12: putfield # 2 // Alan a: I 5: dönüş LineNumberTable: satır 15: 0 satır 16: 5 LocalVariableTable: Başlangıç Uzunluğu Yuva Adı İmza 06 0. dır-dir Lcom / dskj / jvm / bayt kodu / MyTest1; 06 1 bir ben } SourceFile: "MyTest1.java"

Java bayt kodu onaltılık

Mac işletim sistemi altında Önermek MyTest1.class dosyasının onaltılı biçimini görüntülemek için Hex Fiend aracını kullanın.

Onaltılık metin, sonraki analiz ve kullanım için aşağıdaki gibidir:

CA FE BA BE 0000003400180A 00040014090003001507001607001701000161010001490100063C 696E 69743E 010003282956010004436F 646501000F 4C 696E 654E 756D 6265725461626C 650100124C 6F 63616C 5661726961626C 655461626C 650100047468697301001F 4C 636F 6D 2F 64736B 6A 2F 6A 766D 2F 62797465636F 64652F 4D 7954657374313B 01000467657441010003282949010004736574410100042849295601000A 536F 7572636546696C 6501000C 4D 7954657374312E 6A 6176610C 000700080C 0005000601001D 636F 6D 2F 64736B 6A 2F 6A 766D 2F 62797465636F 64652F 4D 7954657374310100106A 6176612F 6C 616E 672F 4F 626A 65637400210003000400000001000200050006000000030001000700080001000900000038000200010000000A 2A B700012A 04 B50002 B100000002000A 0000000A 00020000000600040008000B 0000000C 0001000 0000A 000C 000D 00000001000E 000F 000100090000002F 00010001000000052A B40002 AC 00000002000A 0000000600010000000B 000B 0000000C 000100000005000C 000D 0000000100100011000100090000003E 00020002000000062A 1B B50002 B100000002000A 0000000A 00020000000F 00050010000B 00000016000200000006000C 000D 0000000000000600050006000100010012000000020013

Java bayt kodu yapısının analizi

Cephe her şeyin habercisi, yoğun analiz bölümüne gelin.

Java bayt kodunun genel yapısı aşağıdaki şekilde gösterilmektedir Aşağıdaki şekil, bayt kodu yapısında farklı enlemlerde bulunan anahtar içeriği göstermektedir.

Java bayt kodunun genel yapısı:

Tam Java bayt kodu yapısı diyagramı:

Sonraki Birleştirmek Onaltılık formattaki sınıf dosyası, hangi içeriğin dahil olduğunu analiz etmek için Java bayt kodu dosyasına bakın.

1) 4 bayt, Sihirli Sayı

Sihirli sayı, değer Java'nın kurucusu James Gosling tarafından formüle edilen 0xCAFEBABE'dir.

2) 2 + 2 bayt, Sürüm

Minor_version ve major_version dahil, major_version: 1.1 (45), 1.2 (46), 1.3 (47), 1.4 (48), 1.5 (49), 1.6 (50), 1.7 (51), 1.8 (52), 1.9 (53) ), 1.10 (54)

3) 2 + n bayt, Sabit Havuz

Dize sabitleri, sayısal sabitler vb. Dahil.

4) 2 bayt, Erişim Bayrakları

Erişim işareti, mevcut sınıfın genel, nihai, soyut vb. Olup olmadığını, belirli belirli gereksinimleri karşılayıp karşılamadığını işaretleyin.

5) 2 bayt, Th dır-dir Sınıf adı

Mevcut sınıfın adı

6) 2 bayt, Süper Sınıf Adı

Mevcut sınıfın ait olduğu ana sınıfın adı

7) 2 + n bayt, Arayüzler

Mevcut sınıf tarafından uygulanan arayüz

8) 2 + n bayt, Alanlar

Alan tablosu, mevcut sınıfın alanlarının çeşitli bilgilerini açıklar

9) 2 + n bayt, Yöntemler

Metot tablosu, mevcut sınıf tarafından tanımlanan metot, içeriğin bu kısmının anlaşılması, yukarıdaki bayt yapısına göre nispeten zordur.

Yöntem, sınıflarımızdan birinin tanımında en yaygın olanı olduğu için, yöntem imzalar, erişim değiştiriciler, adlar, yöntem yürütme kodu mantığı, dönüş değerleri vb. Dahil olmak üzere bir dizi önemli bilgi içerir.

Bu yöntemler ayrıca bilgi biçiminde derlenmiş bayt kodu sınıf dosyasında saklanır.Ardından, JVM bayt kodu dosyasını çalıştırdığında, belirli bir yöntemi çağırdığınızda, JVM yazdığınız kaynak koda dayalı olabilir. Amaç, bayt kodundaki talimatları yürütmektir.

Bu yöntem için, JVM'de, en sonunda yürütülecek bir talimat oluşturulur, yani bayt kodunda oluşturulan her bir talimat, kaynak kodu dosyasındaki her kaynak kod satırına karşılık gelir.

Bu talimatlar ayrıca aload_0, iload_1, vb. Gibi anımsatıcı olarak da adlandırılabilir.

10) 2 + n bayt, Nitelikler

Ek özellikler

Sınıf bayt kodunda iki veri türü vardır:

  • Bayt verisi doğrudan miktarı: Bu temel veri türüdür. Dört türe ayrılmıştır: sırasıyla 1 bayt, 2 bayt, 4 bayt ve 8 bayttan oluşan genel verileri temsil eden u1, u2, u4 ve u8.

  • Tablo (dizi), bileşik bir veri yapısıdır Tablo, birden çok temel veriden veya önceden belirlenmiş bir sıradaki diğer tablolardan oluşan büyük bir veri koleksiyonudur. Tablonun bir yapısı vardır ve yapısı şu şekildedir: Tabloyu oluşturan bileşenlerin konumu ve sırası kesin olarak tanımlanmıştır.

Daha sonra, bir bayt kodu dosyasını analiz etmek için javap -verbose komutunu kullandığımızda, sihirli numarayı, sürüm numarasını, sabit havuzu, erişim bayrağını, sınıf bilgilerini, sınıf değişkenlerini, sınıf üye değişkenlerini ve bayt kodu dosyasının sınıflarını analiz edeceğiz. Yapım yöntemi ve sınıftaki yöntem bilgileri.

4.1 Sihirli sayı

Sihirli sayı: Tüm .class bayt kodu dosyalarının ilk 4 baytı sihirli sayılardır.Dosyadaki sihirli sayı: CA FE BA BE ve sihirli sayı sabit bir değerdir: 0xCAFEBABE (kahve bebeği?) Bu değer elde edilir Çok "romantik", rolü, bu dosyanın sanal makine tarafından kabul edilebilecek bir Sınıf dosyası olup olmadığını belirlemektir.

4.2 sürüm numarası

Sürüm numarası: Sihirli sayıdan sonraki 4 bayt, Sınıf dosyasının sürüm bilgisidir, ilk iki bayt, ikincil sürümü (alt sürüm numarası) ve son iki bayt, ana sürümü (ana sürüm numarası) temsil eder.

Buradaki sürüm numarası 00000034, ondalık sayıya dönüştürülmüştür (3 * 16, 1 + 4 = 52 kuvvetine), bu, alt sürüm numarasının 0 ve ana sürüm numarasının 52 olduğu anlamına gelir.

Bu nedenle, dosyanın sürüm numarası: 1.8.0. Bunu java -version komutu ile doğrulayabilirsiniz. Java'nın sürüm numarası 45'ten başlar ve JDK1.0'dan sonraki ana sürüm numarası, JDK1.1 (45), JDK1.2 (46) ve benzeri JDK1.8 (52) gibi 1 artar.

4.3 Sabit Havuz

Sabit havuz (sabit havuz): Ana sürüm numarasından hemen sonra sabit havuz girişi bulunur.

Bir Java sınıfında tanımlanan birçok bilgi, sabit havuz tarafından korunur ve açıklanır.Sabit havuz, Sınıf dosyasının kaynak deposu olarak kabul edilebilir.Örneğin, Java sınıfında tanımlanan yöntem ve değişken bilgileri sabit havuzda saklanır. içinde. Sabit havuzdaki sabitlerin sayısı sabit olmadığından, sabit havuzun girişine sabit havuz kapasitesi sayım değerini (sabit_havuz_sayısı) temsil eden u2 tipi bir verinin yerleştirilmesi gerekir.

Buradaki kapasite sayımı 1'den başlar, onaltılık sayı 0018'dir ve ondalık sayı 24'tür, bu da sabit havuzda 24 sabit olduğu anlamına gelir ve indeks değeri 1'den 24'e kadar değişir.

Sabit havuz dizisindeki öğelerin sayısı = sabit havuzların sayısı-1 (bunlardan 0 geçici olarak kullanılmaz), bu nedenle Java bayt kodu dosyasında sabit_havuzda yalnızca 23 öğe sabiti görülür. Öyleyse neden kapasite sayımı 0'dan başlamıyor? Spesifik nedenler bir sonraki bölümde açıklanmaktadır.

Sabit havuz ana İki tür sabit saklanır:

  • Değişmezler: Metin dizeleri, Java'da son olarak bildirilen sabit değerler vb.

  • Sembol referansları: sınıfların ve arayüzlerin global nitelikli isimleri, alan adları ve tanımlayıcıları, yöntem isimleri ve tanımlayıcıları vb.

4.3.1 Sabit havuzun genel yapısı

Java sınıfına karşılık gelen sabit havuz ana Sabit havuzların sayısı ve sabit havuz dizisinden (sabit tablo) oluşur.

Sabit havuzların sayısı, ana sürüm numarasını hemen takip eder ve 2 baytı kaplar; sabit havuzlar dizisi, sabit havuzların sayısını hemen izler. Sabit havuz dizisi ile genel dizi arasındaki fark, sabit havuz dizisindeki öğelerin türü ve yapısının farklı olması ve uzunluğunun elbette farklı olmasıdır; bununla birlikte, her öğenin ilk verisi u1 türündedir ve bayt 1 baytlık bir bayrak bitidir.

JVM sabit havuzu ayrıştırdığında, u1 türüne göre öğenin belirli türünü elde edecektir. Sabit havuz dizisindeki eleman sayısı = sabit havuz sayısı-1 (bunlardan 0'ı geçici olarak kullanılmaz), amacın bazı sabit havuz indeks değerlerinin verilerini belirli koşullar altında karşılamak olduğunu belirtmek gerekir. "Havuz" kelimesinin anlamı; temel neden, 0 indisinin de bir sabit (ayrılmış sabit) olmasıdır, ancak sabit tabloda yoktur, bu sabit değere karşılık gelir; bu nedenle, sabit havuzun indisi 0 yerine 1'den başlar.

4.3.2 Sabit Havuz Proje Tipi

Sınıf dosya yapısındaki sabit havuzda aslında 14 veri türü vardır.JDK1.7'den sonra 12 ~ 14 veri türü eklenmiştir (yeni üç tür: CONSTANT_MethodHandle_info, CONSTANT_MethodType_info, CONSTANT_InvokeDynamic_info), ana Dinamik dil çağrılarını daha iyi desteklemektir. Bununla birlikte, en sık kullanılanlar aşağıda listelenmiştir ve 11 genel veri türünü listeler:

Yukarıdaki sabitler "SABİT" ile başlayan ve "bilgi" ile biten sabit isimlerdir. Her sabit farklı bir bilgi bölümü içerir ve bunu her bölümün kendisinin başlangıç ve bitiş konumlarına göre analiz edebiliriz.

Analiz için iki temsili sabiti çıkarın:

CONSTANT_Utf8_info

Bu etiketin değeri 1 ise, 1 bayt yer kaplar, UTF-8 kodlanmış dizeyi temsil eder; uzunluk, 2 bayt kaplar, örneğin, uzunluk değeri 4'tür, yani uzunluğun altından okunur 4 bayt uzunluğunda bir dizi.

Bu, CONSTANT_Utf8_info'nun belirli metin içeriğini temsil eder. Yani uzunluğa göre okumayı bitirmek için kaç bayt okumam gerektiğini bilebiliriz Bu baytlar baytlarla temsil edilir.

CONSTANT_Fieldref_info

Etiket U1 tipindedir ve değeri 9'dur. Her ikisi de U2 tipinde iki indeks değeri vardır. İlk indeks, beyan edilen alanın CONSTANT_Class_info sınıfına veya arayüz tanımlayıcısına işaret eden indeks öğesini temsil eder ve ikinci indeks, CONSTANT_NameAndType_info alan tanımlayıcısına işaret eden indeks öğesini temsil eder.

Spesifik olarak, bir alan tanımladığımızda, belirli bir sınıfa eklenmesi gerektiği anlaşılabilir, bu nedenle önce sınıf bilgisini indekslememiz gerekir.Ayrıntılar için CONSTANT_Class_info'ya bakabilirsiniz.Etiketi 7 değeriyle U1 tipindedir ve indeksi temsil eder Tam nitelikli ad sabiti öğesinin indeksinin anlaşılması kolaydır.

Daha sonra bu alanın tanımlayıcısını bulun, burada CONSTANT_NameAndType_info dizinini gösterir, etiketi U1 tipidir, değeri 12'dir, iki dizinin açıklamasına göre alan veya yöntemin adı ve alanın veya yöntemin tanımlayıcısı olarak anlaşılabilir İlgili alanları ve yöntemleri kaynak kodda bulabilirsiniz.

4.3.3 Sabit havuz yapısının analizi

Daha sonra, Java bayt kodu dosyasındaki sabit_pool sabit havuzuna karşılık gelen onaltılık Java bayt kodunu yukarıda bahsedilen Java bayt kodu yapısı özet tablosuna göre analiz ediyoruz.

Java bayt kodu onaltılı:

9. konumdan başlayan onaltılık

0A 000400140A, değerin 10 olduğu ve bayt kodu yapı tablosundan 10 değerinin bulunduğu, CONSTANT_Methodref_info olduğu anlamına gelir, iki indeks değeri vardır, ilk indeksin işgal ettiği bayt 0004 ondalık 4'e dönüştürülür, İki dizinin işgal ettiği bayt 0014, ondalık olarak 20'ye dönüştürülür.

Java bayt kodu dosyasındaki Sabit havuz tanımından şunları görebilirsiniz:

Sabit havuz: # # 1 = Methodref # 4. # 20 // java / dil / Nesne. " < içinde > ": V

4. ve 20. konumlara dizin oluşturun ve bu iki dizin öğesini sabit havuzdan aşağıdaki gibi bulun:

# 4 = Sınıf # 23 // java / dil / Nesne # 20 = NameAndType # 7: # 8 // " < içinde > ": V

Bu iki dizin yapı tablosuna karşılık gelebilir. Bunlar arasında, # 4 ile gösterilen sınıfın tam nitelikli adı java / lang / Object ve dizin 20 konum referansı # 7: # 8'dir. 7. ve 8. bulmaya devam edin:

# 7 = Utf8 < içinde > # 8 = Utf8 V

16. bitten başlayarak onaltılık

0900030015 Bu bayrak bitinin değeri 09'dur ve bayt kodu yapı tablosunda bulunan 9 değerine sahip sabit CONSTANT_Fieldref_info'dur, ardından 3 ve 21'in onaltılık dönüşümüne karşılık gelen iki dizin gelir.

# 2 = Alan referans # 3. # 21 // com / dskj / jvm / bayt kodu / MyTest1.a: I

Aşağıda gösterildiği gibi 3 ve 21 numaralı iki dizin öğesi vardır:

# 3 = Sınıf # 22 // com / dskj / jvm / bytecode / MyTest1 # 21 = NameAndType # 5: # 6 // a: I

Dizin öğesi # 3, dizin öğesi # 22'ye ve dizin öğesi # 21, dizin öğesi # 5: # 6'ya karşılık gelir

# 22 = Utf8 com / dskj / jvm / bayt kodu / MyTest1 # 5 = Utf8 a # 6 = Utf8 I

Yukarıdakine göre, # 5 ile gösterilen değişken adı a'dır ve # 6 ile gösterilen a değişkeninin dönüş tipi, int tipi olan I'dir. Ayrıca, com / dskj / jvm / bytecode / MyTest1.a'ya karşılık gelen # 2 = Fileldref'i de bilin: I.

MyTest1 sınıfının değişkenlerine karşılık gelen:

private int a = 1;

21. konumdan başlayan onaltılık

070016 Bayrak biti 07'dir, değer 7 baytlık kod yapısı tablosunda karşılık gelen sabit CONSTANT_Class_info'dur, indeks 2 bayt kaplar ve karşılık gelen dönüşüm ondalık olarak 22'dir.

# 3 = Sınıf # 22 // com / dskj / jvm / bytecode / MyTest1 # 22 = Utf8 com / dskj / jvm / bayt kodu / MyTest1

27'den başlayarak onaltılık

Onaltılık bayt kodu dosyası:

01000161010001490100063C 696E 69743E 010003282956010004436F 646501000F 4C 696E 654E 756D 6265725461626C 65

Arama bayrağı biti 01'dir ve değeri 1 olan yapı tablosu sabiti CONSTANT_Utf8-info ve 2 baytı kaplayan uzunluk onaltılık olarak 0001'dir, bu nedenle uzunluk uzunluğu 1'dir (ondalık değere dönüştürülür, yani 0 * 16 + 1'in ilk gücü), sonraki bayt 61'dir ve bunun HexFiend aracıyla bir işaretini gösterdiğini görebilirsiniz.

Böylece, onaltılık bulunan: 01000161

Sabit havuz ayrıca doğrulanır:

# 6 = Utf8 I

Onaltılık bayt kodu dosyası:

010001490100063C 696E 69743E 010003282956010004436F 646501000F 4C 696E 654E 756D 6265725461626C 65 ...

Bayrak biti 01'i aramaya devam edin, 1 değerine sahip yapı toplam tablo sabiti CONSTANT_Utf8-info ve 2 bayt onaltılık kaplayan uzunluk 0001, sonra uzunluk uzunluğu 1 ve sonraki bayt 49. HexFiend aracı sayesinde, I'i işaret ettiğini de görebilirsiniz.

Böylece onaltılık şu bulundu: 01000149

Sabit havuz ayrıca doğrulanır:

# 6 = Utf8 I

Onaltılık bayt kodu dosyası:

0100063C 696E 69743E 010003282956010004436F 646501000F 4C 696E 654E 756D 6265725461626C 65 ...

Bayrak bitini 01, 1 değerine sahip yapı tablosu sabiti SABİT_Utf8-info ve 2 bayt onaltılık alan uzunluğu 0006, ardından uzunluk uzunluğu 6'dır (ondalık değere dönüştürülür, yani 0 * 16 + 6'nın ilk gücü), sonraki 6 bayt 3C 696E 69743E'dir, noktayı HexFiend aracı ile de görebilirsiniz. < içinde > .

Böylece, onaltılık bulunan: 0100063C 696E 69743E

Sabit havuz ayrıca doğrulanır:

# 7 = Utf8 < içinde >

Benzetme yoluyla, sonunda onaltılık bayt kodunu geçecek ve Birleştirmek Bayt kodu yapısı özet tablo analizi, sabit havuzda karşılık gelen bayt kodu içeriğini bulur.

4.4 Erişim logosu

Erişim bayrağı bilgileri, Sınıf dosyasının bir sınıf mı yoksa bir arabirim mi olduğunu, genel olarak tanımlanıp tanımlanmadığını, soyut olup olmadığını ve bir sınıf olup olmadığını ve son olarak bildirilip bildirilmediğini içerir. tarafından Yukarıda MyTest1 kaynak kodu, dosyanın bir sınıf ve herkese açık olduğunu biliyoruz.

Access_Flag erişim bayrağı yapı tablosu:

MyTest1 kategorisinin onaltılık bayt kodundaki konum: 0x 0021

Bu 0x 0021, ACC_PUBLIC ve ACC_SUPER'ı gösteren erişim bayrağı yapı tablosundaki 0x 0020 ve 0x 0001 birleşimidir.

genel sınıf com.dskj.jvm.bytecode.MyTest1 ... bayraklar: ACC_PUBLIC, ACC_SUPER

Ziyaretten sonra işaret Th dır-dir Sınıf Adı, karşılık gelen onaltılık 0x 0003

Sabit havuz proje tipinde bulun:

# 3 = Sınıf # 22 // com / dskj / jvm / bytecode / MyTest1

Th dır-dir Sınıf Adı Süper Sınıf Adı olduktan sonra karşılık gelen onaltılık 0x 0004

Sabit havuz proje tipinde bulun:

# 4 = Sınıf # 23 // java / dil / Nesne

Arayüzler

Arayüz iki bölümden oluşur; ilki interfaces_count (arayüz sayısı) ve ikinci kısım arayüzler (arayüzün adı).

Bu sınıfa karşılık gelen geçerli onaltılık sistem: 0000, ondalığa dönüştürülmüş, bu da geçerli sınıfın herhangi bir arabirim uygulamadığını gösterir.

Bu nedenle, bu arayüzler arayüz tablosu artık görünmeyecektir. Arabirim sayısı interfaces_count 1'den büyük veya eşitse, bu arabirimler arabirim tablosu mevcuttur.

4.5 Saha Tablosu

Alanlar

Alan iki bölümden oluşur, birincisi Fields_count (alan sayısı) ve ikinci bölüm alanlar (alan adı).

Bu sınıfa karşılık gelen geçerli onaltılık: 0001, bu sınıfta bir alan olduğunu gösteren 1 ondalık değerine dönüştürülür.

Saha tablosu koleksiyonu

Alan tablosu, sınıflarda ve arayüzlerde bildirilen değişkenleri tanımlamak için kullanılır. Buradaki alanlar, sınıf düzeyinde değişkenleri ve örnek değişkenleri içerir, ancak yöntemlerin içinde bildirilen yerel değişkenleri içermez.

Saha tablosu yapısı:

Birincisi, genel, özel, korumalı, son, soyut vb. Erişim bayraklarıdır.

İkinci isim indeksi ve üçüncü tanımlayıcı indeksi, bir alan yapısının tam bilgisini oluşturur.

Öznitelik_sayısı, alanın benzersiz bilgisidir. Değer 0 ise, aşağıdaki öznitelikler mevcut olmayacaktır.

Belirli yapı örneği:

Geçerli sınıf alanına karşılık gelen onaltılık aşağıdaki gibidir:

field_info { u2 erişim_flags; 0002 u2 ad_indeksi; 0005 u2 descriptor_index; 0006 u2 attributes_counts; 0000 attribute_info öznitelikleri; }

0x0002, erişim bayrağı yapı tablosundaki ACC_PRIVATE'e karşılık gelir.

0x0005 ad indeksi ve 0x0006 tanımlayıcı indeksi, 5 ve 6 olarak onaltılık tabana dönüştürülür ve sonuç sabit havuz yapısı tablosundan aranır:

# 5 = Utf8 a # 6 = Utf8 I

Ek özniteliklerin sayısı 0x0000 olup, ondalık 0'a dönüştürülür ve ek öznitelikler görünmez.

4.6 Yöntem tablosu

0003 // yöntemler_sayısı 0001 // access_flags 0007 // isim_indisi 0008 // descriptor_index 0001 // öznitelik_sayısı 0009 // öznitelik_adı_indisi 00000038 // özellik_uzunluğu 0002 // maksimum ek öznitelik yığınları 0001 // ek özniteliklerin max_locals 0000000A // ek özelliklerin kod uzunluğu 2A B700012A 04 B50002 B1 // byte of code_lengthc uzunluğu, çalıştırılan belirli bytecode komutu 00000002000A 0000000A 00020000000600040008000B 0000000C 00010000000A 000C 000D 00000001000E 000F 000100090000002F 00010001000000052A B40002 AC 00000002000A 0000000600010000000B 000B 0000000C 000100000005000C 000D 0000000100100011000100090000003E 00020002000000062A 1B B50002 B100000002000A 0000000A 00020000000F 00050010000B 00000016000200000006000C 000D 0000000000060005000600010001001200000000020013

Yöntemler

Yöntem iki bölümden oluşur; ilki method_count (yöntem sayısı) ve ikinci bölüm yöntemler (yöntemin adı).

Bu sınıfa karşılık gelen geçerli onaltılık: 0003, 3'ün ondalık değerine dönüştürülür ve bu sınıfta üç yöntem olduğunu gösterir.

Üç yöntem şunlardır:

setA, getA ve parametresiz varsayılan yapım yöntemi.

Yöntem tablosu yapısı:

Spesifik anlam, yukarıda bahsedilen alan tablosu yapısına benzer.

Access_flags'e karşılık gelen onaltılık: 0001 Bayrak yapısı tablosunda ACC_PUBLIC olarak bakın.

name_index isim dizini onaltılık 0007'ye karşılık gelir tanımlayıcı_indeks tanımlayıcı dizin onaltılık 0008'e karşılık gelir

Sırasıyla 7 ve 8 ondalık sayılarına dönüştürün ve sonucu sabit havuzda bulun:

# 7 = Utf8 < içinde > // Bu sınıfın yapım yöntemini gösterir # 8 = Utf8 V // Herhangi bir parametre almayan ve sonuç döndürmeyen tanımlayıcı

attributes_count, onaltılı: 0001'e karşılık gelir ve numarası 1'dir, bu da ek bir öznitelik olacağını gösterir. Aynı zamanda bir niteliğin olduğunu da gösterir.

Yöntemin öznitelik yapısı:

Yöntemdeki her öznitelik bir atrribute_info yapısıdır.

atrribute_info { u2 atrribute_name_index; u4 öznitelik_uzunluğu; u1 bilgisi; }

attribute_name_index onaltılı gösterimde 0009'a karşılık gelir.Sabit havuz yapısı tablosunda sonucu bulun:

# 9 = Utf8 Kodu

Varsayılan yapım yöntemi gibi bayt kodundaki her yöntemde yansıtılabilir:

public com.dskj.jvm.bytecode.MyTest1; tanımlayıcı: V bayraklar: ACC_PUBLIC Kod: ...

Daha sonra atrribute_length'e göre, karşılık gelen onaltılık sistem 00000038'dir ve 3 * 16 + 8 = 56'nın gücü olarak ondalık sisteme dönüştürülür.

Kod özniteliğinin belirli değeri olarak onaltılık tabanın arkasında 56 baytın bulunduğunu açıklayın.

Yöntem tablosu yapısı:

İlk üç alan field_info ile aynıdır.

method_info { u2 access_flags; u2 name_index; u2 descriptor_index; u2 attributes_count; attribute_info öznitelikleri }

Yöntemin öznitelik yapısı:

  • JVM bazı atrribute ayırdı, ancak derleyicinin kendisi de çalışma zamanı kullanımı için sınıf dosyasına kendi atrribute'unu yazabilir.

  • Farklı öznitelikler, öznitelik_adı_indisi ile ayırt edilir.

Kod yapısı:

Kod özniteliğinin rolü, ilgili bayt kodu gibi yöntemin yapısını kaydetmektir.

  • öznitelik_uzunluğu özniteliğin içerdiği baytların sayısını belirtir ve atrribute_name_index ve öznitelik_uzunluk alanlarını içermez.

  • max_stack, bu yöntem çalıştığında herhangi bir anda ulaşılabilen işlemsel yığının maksimum derinliğini temsil eder. // 0002

  • max_locals, gelen parametreleri temsil etmek için kullanılan yerel değişkenler dahil, yöntemin yürütülmesi sırasında oluşturulan yerel değişkenlerin sayısını temsil eder. // 0001

  • code_length, yöntemde bulunan bayt kodunun bayt sayısını ve belirli talimat kodunu temsil eder. Anımsatıcı olarak da bilinir. // 0000000A, 10'luk bir ondalık değere dönüştürülür ve bunu 10 bayt izler 2A B700012A 04 B50002 B1 Bunlar, yapım yönteminin bayt koduna karşılık gelen bayt koduna özgü talimatlardır:

Peki, bu onaltılık sayılar aşağıdaki anımsatıcılara nasıl karşılık gelir?

Görüntülemek için jclasslib aracını (bayt kodu görüntüleme aracı, IDEA eklenti kurulumunu destekleyin) kullandığımızda, belirli ayrıntılı açıklamayı görüntülemek için anımsatıcının bağlantısına tıklayın Oracle resmi web sitesine atlayacaktır. İlk anımsatıcı: 0: aload_0 Bağlantıyı açın ve şunları görebilirsiniz:

bağlantı adresi:

https://docs.oracle .com /javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.aload_n

Spesifik açıklama aşağıdaki gibidir:

aload_ < n > Operasyon Yerel değişkenden yükleme referansı Biçim aload_ < n > Formlar aload_0 = 42 (0x2a) // Buradan aload_0'a karşılık gelen ondalık sayının 42 olduğunu ve onaltılık tabana dönüştürülen 0x2a olduğunu görebilirsiniz, bu da bayt kodu dosyasında 2A'ya karşılık gelir aload_1 = 43 (0x2b) aload_2 = 44 (0x2c) aload_3 = 45 (0x2d) Açıklama < n > bir dizin olmalı yerel değişken dizisi nın-nin geçerli çerçeve (§2.6). yerel değişken < n > bir referans içermelidir. objectref içinde yerel değişken < n > dır-dir üzerine itildi işlenen yığını. Bu < n > Geçerli yığın çerçevesinin yerel değişken dizisine bir dizin olmalıdır, < n > Konumdaki yerel değişken, adresinde bulunan bir referans içerecektir. < n > Konumdaki yerel değişkenin bu referansı yığının en üstüne itilecektir (çalışmaya hazır). İkinci anımsatıcı: 1: özel # 1'i çağırın // Yöntem java / lang / Object. " < içinde > ": V Bağlantı adresi: https://docs.oracle .com /javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.invokespecial özel Operasyon Örnek yöntemini çağırın; süper sınıf, özel ve örnek başlatma yöntemi çağrıları için özel işlem Biçim özel indexbyte1 indexbyte2 Formlar invokespecial = 183 (0xb7) Operand Yığını ..., nesne referansı, ...
  • Belirli bayt kodu, yöntem çağrıldığında sanal makine tarafından yürütülen bayt kodudur.

  • exception_table, işte istisnaları ele almak için bilgiler.

  • Her bir exception_table girişi, start_pc, end_pc, handler_pc ve catch_type'dan oluşur.

  • start_pc ve end_pc, kod dizisinde start_pc'den end_pc'ye kadar olan talimatlar tarafından (start_pc dahil ancak end_pc hariç) atılan istisnaların bu giriş tarafından ele alınacağını belirtir.

  • handler_pc, istisnayı işleyen kodun başlangıcını temsil eder. catch_type, işlenecek istisna türünü belirtir ve sabit havuzdaki bir istisna sınıfına işaret eder. Catch_type 0 olduğunda, tüm istisnaları ele almak anlamına gelir.

Ek özellikler

LineNumberTable: Bu özellik, kod dizisindeki bayt kodu ile Java kodunun satır sayısı arasındaki ilişkiyi temsil etmek için kullanılır. Bu öznitelik, hata ayıklama sırasında kod yürütme satırlarının sayısını bulmak için kullanılabilir.

LocalVariableTable: yerel değişken tablosu, mevcut sınıfta yalnızca bir yerel değişken vardır ve bu yerel değişken, dır-dir Mevcut nesne.

Yerel değişken tablosu öznitelikleri, satır numarası tablo özniteliklerine benzer.

Lütfen aklınızda bulundurun:

Java kaynak kodu perspektifi: Bu, doğrudan Java sınıfının örnek yönteminde kullanılabilir dır-dir .

Java bayt kodu perspektifi: Java sınıfındaki statik olmayan yöntem, yani örnek yöntemindeki th dır-dir Aslında, derleyici tarafından yöntemin ilk parametresi olarak örtük olarak iletilir (Python'daki yönteme biraz benzer, yöntemdeki ilk parametre mevcut nesnenin kendisini temsil eden bir öz değişkeni geçecektir). Bu, her örnek yönteminin içine sorunsuz erişim sağlar dır-dir . Başka bir deyişle, sınıfın örnek yöntemi için en az bir LocalVariable yerel değişkeni vardır ve bu değişken, dır-dir .

4.7 Alan / Yöntem Tanımlayıcı

JVM spesifikasyonunda, her değişken / alan açıklama bilgisine, açıklama bilgisine sahiptir ana İşlev, alanın veri türünü, yöntemin parametre listesini (sayı, tür ve sıra dahil) ve dönüş değerini tanımlamaktır. Tanımlayıcı kurallara göre, temel veri türü ve dönüş değerini temsil etmeyen void türü bir büyük harf karakteriyle temsil edilir ve nesne türü, L karakteri artı nesnenin tam nitelikli adı ile temsil edilir. Bayt kodu dosyalarının boyutunu sıkıştırmak amacıyla, temel veri türleri için JVM, aşağıda gösterildiği gibi temsil etmek için yalnızca büyük harf kullanır:

B-bayt, C-karakter, D-double, F-float, I-int, J-long, S-short, Z-boolean, V-void, L-nesne türü, örneğin Ljava / lang / String;

Dizi türü: Dizi türleri için her boyut bir ön

Süper güzel el boyaması 2019'u incelediğinizde hangi duvar kağıdını seçersiniz?
önceki
Mobil geliştirme, App Factory çağına girdi
Sonraki
Ortalama maaş 16.000 yuan'a ulaştı! Birinci kademe şehirlerdeki 2020 programcı maaşları ortaya çıktı
Anlamak için bir iş bulmayı beklemeyin: Bir programcının sadece kod yazması imkansızdır! pişman olma
Jack Ma, Alibaba işten çıkarma söylentilerine yanıt veriyor; Yang Yuanqing düzenli olarak ayrılma hakkında konuşuyor; Arch Linux 2020.01.01 yayınlandı | Geek Manşetleri
Komik: Neden bazı web sitelerinde yıl sonunda tarih kargaşası oluyor?
Ubuntu'nun on yıllık incelemesi
Gelişmekte olan ilk on ön uç çerçevesi
TIOBE Ocak programlama dili sıralaması: C dili bir kez daha "C-bit" olarak tanıtıldı
IDEA Community Edition Tomcat'i desteklemiyor mu? Mükemmel bir çözüm
Açıklığa kavuşturmak! Kadın programcılar neden daha fazla para kazanıyor? Bu 4 büyük numara, para kazanmak için Python'u yan hat olarak kullanın
Microsoft, LinkedIn'i 26 milyar dolara satın aldıktan sonra hiçbir şey yapmadı mı?
"Linux bilmiyorsanız, nasıl programcı olabilirsiniz?" Hardcore programcı: Hiçbir şey yapamam
Trendin ardından, Google sadece bir taklittir
To Top