Şimdi ise ByteCodeTest.java sınıfına 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.
ByteCodeTest.java sınıfımız şöyle idi:
Şimdi, bu sınıfa selamVer() methodumuzu ekliyorum:public class ByteCodeTest {
int i;
public ByteCodeTest() {
i = 0;
}
public void artir() {
i = i + 1;
}
public void artirAlternatif() {
i++;
}
}
public void selamVer() {Bu methodun JAVA bytecode'una baktığımızda ise:
String s = "s" + "e" + "l" + "a" + "m";
s += "sana";
s += "arkadas";
System.out.println(s);
}
public void selamVer();Şeklinde uzunca bir komut listesi çıkıyor karşımıza (bazı komutlar sayfaya sığmadığından aşağıdaki satıra taşıyorlar).
Code:
0: ldc #3 // String selam
2: astore_1
3: new #4 // class java/lang/StringBuilder
6: dup
7: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
10: aload_1
11: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
14: ldc #7 // String sana
16: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_1
23: new #4 // class java/lang/StringBuilder
26: dup
27: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
30: aload_1
31: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
34: ldc #9 // String arkadas
36: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
39: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
42: astore_1
43: getstatic #10 // Field java/lang/System.out:Ljava/io/PrintStream;
46: aload_1
47: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
50: return
Dikkat çeken ilk şey, JAVA compiler'ın
String s = "s" + "e" + "l" + "a" + "m";
şeklinde anlamsız bir şekilde atama yaptığımız satırı
0: ldc #3 // String selamhaline getirebilecek kadar akıllı olmasıdır.
Buradan sonra işler biraz karışıyor. 3: no'lu satırda gördüğümüz
3: new #4 // class java/lang/StringBuilderkomutu bize isteğimiz dışında bir StringBuilder nesnesi oluşturulduğunu ve sonraki satırlarda constructor'ının çağırıldğını,
11: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;komutuyla StringBuilder sınıfının append() methodunun çağırıldığını,
14: ldc #7 // String sanasatırları ile "sana" diye yeni bir string değişkeninin oluşturulduğunu, append() methodu ile birleştirildiğini toString() ile string'e dönüştürülüp yeni bir string olarak saklandığını;
16: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_1
23: new #4 // class java/lang/StringBuilderile bir StringBuilder nesnesi daha oluşturulduğunu
34: ldc #9 // String arkadassatırı ile "arkadas" diye yeni bir string değişkeninin oluşturulduğunu, append() methodu ile birleştirildiğini toString() ile string'e dönüştürülüp yeni bir string olarak saklandığını görüyoruz.
Yani buradan anlayacağımız, basit bir string ekleme işlemi için, isteğimiz dışında, bir sürü StringBuilder nesnesi oluşturuluyor, sık sık append() ve toString() methodları çağırılıyor ve bir sürü yeni string oluşturuluyor. Bu işlemi yüzlerce defa tekrarladığımız bir yazılım yazdığımızı düşünmek bile garip geliyor.
Peki, arka planda neler döndüğünü anladıktan sonra, aynı işlevi yerine getiren daha temiz bir kod yazabilir miyiz? Bir deneyelim...
Bu sınıfa selamVerAlternatif() isimli yeni methodumuzu ekliyorum:
public void selamVerAlternatif() {Burada yaptığımız şey StringBuilder nesnesinden bir örnek oluşturup append() ve toString() methodlarını ihtiyacımız olan yerlerde kullanmaktan başka bir şey değil.
StringBuilder sb = new StringBuilder("s" + "e" + "l" + "a" + "m");
sb.append("sana");
sb.append("arkadas");
System.out.println(sb.toString());
}
JAVA bytecode'una bakalım:
public void selamVerAlternatif();Yani, tam ihtiyaç duyduğumuz şekilde, StringBuilder nesnesinden bir örnek oluşturup iki defa append() ve bir defa da toString() methodlarının kullanıldığını görebiliyoruz. Bu iyileştirmenin, daha az bellek işlemi gerçekleşiyor olacağından, yazılımımıza hız katacağı da aşikar.
Code:
0: new #4 // class java/lang/StringBuilder
3: dup
4: ldc #3 // String selam
6: invokespecial #12 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
9: astore_1
10: aload_1
11: ldc #7 // String sana
13: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
16: pop
17: aload_1
18: ldc #9 // String arkadas
20: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
23: pop
24: getstatic #10 // Field java/lang/System.out:Ljava/io/PrintStream;
27: aload_1
28: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
31: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
34: return
Daha önce dediğim gibi, JAVA bytecode hakkında hiçbir şey bilmeden, sadece, StringBuilder kullanmanın daha iyi olacağını birisinden duyduğunuz için, yukarıdaki satırları aynen yazıyor olabilir hatta daha iyisini de yapıyor olabilirsiniz. Ancak JAVA bytecode'unu aslında neler olup bittiğini anlamak için kullandığınız zaman siz hep bir adım önde olursunuz.
JAVA bytecode serisine bu yazı ile son vermeyi düşünüyorum.
Hiç yorum yok:
Yorum Gönder