5 Nisan 2012 Perşembe

JAVA Bytecode Ayrıntılı İnceleme

JAVA Bytecode Nasıl Elde Edilir? başlıklı önceki yazımda, hazırlamış olduğum ByteCodeTest isimli sınıfın JAVA bytecode'unu nasıl elde edeceğimizi açıklamıştım. Bu yazımda ise, yazmış olduğum JAVA kodlarını ve karşılık gelen JAVA bytecode'larını inceleyeceğim.

Bu amaçla ilk önce ByteCodeTest.java sınıfını aynen kullanarak karşılaştırma yapacağım, daha sonra ise bu sınıfa bir method daha ekleyip string ekleme / birleştirme (string concatenation) işlemini JAVA bytecode'ları yardımıyla inceleyeceğim ve basit ama önemli bir konudan bahsedeceğim... (Devam)

ÖNEMLİ NOT : Bloglarda yazılan yazıları kopyalayıp kendi sitenizde, forumlarda yayınlamak çok hoş gibi görünse de aslında makaleyi yazan kişinin cesaretini kıran, motivasyonunu yok eden bir davranıştır. Burada yazılan yazıların da bir kısmını ya da tamamını kaynak göstermeden kopyalayan kişi düdüklü tenceredir, Sarkozy'dir.

Şimdi, sınıfımızın constructor'ı olan:
public ByteCodeTest() {
        i = 0;
}
kodlara karşılı gelen JAVA bytecode'u şu şekilde idi:
public deneme.ByteCodeTest();
    Code:
       0: aload_0      
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0      
       5: iconst_0     
       6: putfield      #2                  // Field i:I
       9: return
 Burada ilginç olan, 1: no'lu satırda invokespecial kodu ile Object sınıfının constructor'ının çağırılıyor olması. Sebebi ise, tabi ki her bir JAVA sınıfının Object sınıfından kalıtım yoluyla elde ediliyor olmasıdır.

Geçelim artir() methoduna. Methodumuz şöyle idi:
public void artir() {
        i = i + 1;
}
Yaptığı iş i global değişkeninin değerini 1 artırmak olan bu methodun JAVA bytecode'u ise:
public void artir();
    Code:
       0: aload_0      
       1: aload_0      
       2: getfield      #2                  // Field i:I
       5: iconst_1     
       6: iadd         
       7: putfield      #2                  // Field i:I
      10: return
şeklinde oluyordu. Şimdi burada 1: no'lu satıra sonra incelemek üzere vurgu yaparak diğer komutlara bakalım.

2: getfield      #2 ile i global değişkeni stack'e alınıyor.
5: iconst_1                      ile değeri bir olan bir int oluşturulup stack'e alınıyor.
6: iadd             stack'teki bu iki değişken, integer toplama ile toplanıyor.
7: putfield      #2 ile toplanan bu değer i global değişkenine atanıyor.


Şimdi de artirAlternatif() methoduna bakıyorum.
public void artirAlternatif() {
        i++;
}
Bu methodun işlevi yukarıdaki artir() methodu ile tamamen aynı. Ancak JAVA bytecode'una baktığımızda bir fark göreceğiz:
public void artirAlternatif();
    Code:
       0: aload_0      
       1: dup          
       2: getfield      #2                  // Field i:I
       5: iconst_1     
       6: iadd         
       7: putfield      #2                  // Field i:I
      10: return
artir() methodunda 1: no'lu satırda
 1: aload_0
komutu varken, artirAlternatif() methodunda 1: no'lu satırda
 1: dup
komutunu görüyoruz. dup komutu duplicate (aynısını yapmak, çoğaltmak) kelimesinin kısaltılmasından oluşmuş olup stack'teki değerin bir kopyasının daha stack'e eklenmesini sağlamaktadır. Bunun haricinde geriye kalan kodların birebir aynı olduğunu görüyoruz.

NOT : İşlevi aynı olan ancak global olan i değişkeni yerine lokal bir integer değişken üzerinde aynı işlemleri yapan yeni methodlar yazdığımızda ise tamamen farklı olan iinc 1,1 gibi bir komutla karşılaşacağız. Bunu da burada anlatmayalım, siz deneyin.

String'ler ile yaptığımız ekleme / birleştirme / concatenation işlemlerini JAVA bytecode bakış açısından bir sonraki yazımda inceleyeceğim. Buradaki basit örnekleri karmaşıklaştırmak, zorlaştırmak istemedim.

Hiç yorum yok:

Yorum Gönder