Minter Coder Hack-Mack-Bi şeyler

04 Eylül

java main metot javac derleyici

Bölüm 1.2: Java main Methodunu Anlamak

Selam gençler;

Bugün java'da main methodunu yazarak artık bir "hello world" klasiğini gerçekleştirmek istiyoruz.

Öncelikle gerekli olan bir şeyimiz var text editor dosyamız yada not tutma uygulamamız.

Bunun içerisine şunları yazmamız yeterlidir.

Şimdi ise artık bunu çalıştırmamız için tabii ki java gerekli java'yı da indirelim linux kullanıcısı iseniz : 

sudo apt-get install openjdk-17-jdk

Bunu indirip artık java kodumuzu ileride çalıştıracağız, şimdilik yazdığımız kodu inceleyelim.

Görüldüğü üzere önceki derse de atıfta bulunacak olursak Zoo.java ekledim ve public class'ımızın da ismini zorunlu olarak Zoo bıraktık ve içerisine bir şeyler yazdık.

 

public class Zoo {
    public static void main(String[] args){
        System.out.println("Hello Minter Coder");
    }
}

 

Görüldüğü üzere bazı keyword'ler var (özel kelimeler) bunları açıklayalım.

 

  • public anahtar kelimesi access modifier (erişim belirteci) olarak adlandırılır ve buna erişimi method'a yada sınıfa erişimin nasıl olacağını belirtir public burda her sınıftan,her paketten erişimin olabileceğini açıklar.
  • static anahtar kelimesi burda bir methodu sınıfa bağlar yani bir methodu static olarak adlandırırsak artık "static method" olarak isimlendirilir ve herhangi bir nesne yaratmadan sadece sınıfın ismini kullanarak bu methodu çağırabiliriz. Örneğin : Zoo.main("MinterCoder") şeklinde
  • void anahtar kelimesi de methot geriye bir şey döner mi dönmez mi onu belirtir. Matematikte ki fonksiyonlar gibi düşünün f(x)=2*x gibi burda mesela fonksiyona x değeri gelse bize 4 dönüyor. Programlama biz eğer ki bir metodu void olarak işaretlersek hiçbir şey dönmeyecek anlamına gelir bu sayede main() metodumuzun da bir şey dönmeyeceğini anlayabiliriz.
  • main() methodu için Java bir tane nesne oluşturmaz ve programın ilk giriş noktasıdır yani uygulama çalıştığı an bu methottan çalışmaya başlar.
  • String[] args ile başlayan kısım ise bir diziyi belirtir. Ve komut satırı argümanı olarak isimlendirilir yani program çalışınca eğer ki biz komut satırından değerler vermişsek bunları args dizisinde tutar ve bunları alıp programımızda kullanabiliriz. Eğer ki String[] args yerine aşağıdaki gibi görmüş olsaydınız :
public static void main(String... args)

 

Burası (String... args) kısmı varargs olarak adlandırılır yani variable argument lists bu da önceki çağırma ile aynıdır.

 

  • System.out.println() de bizim içerisine yazdığımız yazıları console'da göstermek için kullandığımız metotdur.

 

Kodumuzu Derlemek için:

javac Zoo.java

Kodumuzu Çalıştırmak için:

java Zoo

 

 

 

Peki bu çalışma süreci nasıl gerçekleşiyor kısaca buna değinecek olursak tek bir image ile :

 

 

 

Javac toolu ile kodumuzu (Zoo.java) derlediğimizde, compiler kodumuzu bytecode'ye (Zoo) çevirir ve JVM de bu bytecode'yi başarılı bir şekilde çalıştırır.

Peki kaç farklı şekilde biz Java dosyamızda main methodumuzu yazabiliriz ?

Geçerli olan main methodları

public static void main(String[] args) {}
static public void main(String[] args){}
public static void main(String []args){}
public static void main(String[] args){}
public static void main(String args[]){}
public static void main(String... args){}
public static final void main(String[] args){}
public static final void main(String.. args){}
final public static void main(String.. args){}
final public static void main(String[] args){}
final strictfp public static void main(String[] args){}

Geçerli olmayan main methodları

public void main(String[] args){}
abstract public static void main(String[] args){}
static void main(String[] args){}
public void static main(String[] args){}

 

 

Hello World'ün İç Yapısı

 

Şimdi konunun biraz daha derinine inelim.

Biz Zoo.java dosyasına sahiptik.

 

1) Biz "javac" aracı ile kodumuzu derleyip bytecode'ye çeviriyorduk. Bu dosya çıktı olarak bize Zoo diye bir dosya vardi normalde bu Zoo.class'tır yani bizim kodumuzun işletim sistemine değinmeden platformdan bağımsız çıkan bytecode'sidir. Bu bytecode'yi görüntülemek istersek eğer :

 

javap -c Zoo

 

~/Desktop$ javap -c Zoo
Compiled from "Zoo.java"
public class Zoo {
  public Zoo();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #13                 // String Hello Minter Coder
       5: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return
}

 

Kodumuzun çıktısı yukarıdaki gibi olur. Yukarıdaki süreçlerin tamamı "Compile Time" yani derleme zamanında olan süreçlerdir. Bu süreçte çoğunlukla Derleme hatalarına bakılır örneğin kod içerisinde noktalı virgül(;) eklemek unutulmuştur, geçersiz bir main metodu yada bir syntax hatası vardır işte bunlar kontrol edilir.

 

Peki derleme platformlardan bağımsız bir şekilde oldu peki "Runtime (Çalışma)" zamanında ne oluyor ?

 

java Zoo

 

biz bu kodu yazdığımızda artık süreç başlar JVM tek tek şu aşamaları gerçekleştirir:

 

 

1) Şimdi bizim Zoo.class dosyamız vardı bytecode yukarıdaki javac Zoo.java ile oluşturuğu çıktısını aldığımız dosya, işte JVM gider bu dosyanın entrypointini bulur (Zoo.class derlediğimiz dosya Zoo) bu dosyanın yani bizim classımız içerisinde constant pool (sabit havuzu), alanlar, metotlar ve bytecode vardır.Bunları da görüntülemek için :

 

javap -verbose Zoo

 

~/Desktop$ javap -verbose Zoo
Classfile /home/mintercoder/Desktop/Zoo.class
  Last modified Sep 4, 2025; size 418 bytes
  SHA-256 checksum 6986fe8d22619580cf5ad82cd4506e1b13200baf6721b9f90584d335d1f03e3d
  Compiled from "Zoo.java"
public class Zoo
  minor version: 0
  major version: 61
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #21                         // Zoo
  super_class: #2                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #2.#3          // java/lang/Object."":()V
   #2 = Class              #4             // java/lang/Object
   #3 = NameAndType        #5:#6          // "":()V
   #4 = Utf8               java/lang/Object
   #5 = Utf8               
   #6 = Utf8               ()V
   #7 = Fieldref           #8.#9          // java/lang/System.out:Ljava/io/PrintStream;
   #8 = Class              #10            // java/lang/System
   #9 = NameAndType        #11:#12        // out:Ljava/io/PrintStream;
  #10 = Utf8               java/lang/System
  #11 = Utf8               out
  #12 = Utf8               Ljava/io/PrintStream;
  #13 = String             #14            // Hello Minter Coder
  #14 = Utf8               Hello Minter Coder
  #15 = Methodref          #16.#17        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #16 = Class              #18            // java/io/PrintStream
  #17 = NameAndType        #19:#20        // println:(Ljava/lang/String;)V
  #18 = Utf8               java/io/PrintStream
  #19 = Utf8               println
  #20 = Utf8               (Ljava/lang/String;)V
  #21 = Class              #22            // Zoo
  #22 = Utf8               Zoo
  #23 = Utf8               Code
  #24 = Utf8               LineNumberTable
  #25 = Utf8               main
  #26 = Utf8               ([Ljava/lang/String;)V
  #27 = Utf8               SourceFile
  #28 = Utf8               Zoo.java
{
  public Zoo();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."":()V
         4: return
      LineNumberTable:
        line 1: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #13                 // String Hello Minter Coder
         5: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 3: 0
        line 4: 8
}
SourceFile: "Zoo.java"

 

Burda ana amaç .class dosyasının olmasının sebebi ".class" dosyası her tarafta aynı formatta olduğu için Windows,Linux ve MacOS farketmeksizin her tarafta çalışacaktır.

 

2) ClassLoader (Sınıf Yükleyicileri )'dan geçer : Kendi içerisinde Bootstrap vardır ve bu java.lang.Object, String gibi temel classları JDK'den yükler. Bir de Platform / AppClassLoader vardır burda ise bizim belirttiğimiz sınıfları CLASSPATH yada JAR'dan yüklemesini yapar.Örneğin biz String name = "MinterCoder"; yazdığımızda herhangi bir kütüphane eklemesi (java.lang.String) yapmıyoruz çünkü Bootstrap loader bunu bizim için kendisi yapıyor.

3) ByteCode Verifier : Burası JVM için bir güvenlik kapısıdır çünkü bizim JVM'e biz Zoo.class'ı verdik ve direkt JVM bunu çalıştırmaz çünkü burda birkaç kontrol yapar mesela JVM'in çökmesini,bellek taşmasını yada izinsiz erişim var mı yok mu onu kontrol eder. Mesela tür güvenliğine bakar siz String yerine int mi kullandınız ? Erişim güvenliğinde de mesela private olan bir access modifiera erişim mi sağlamaya çalışıyorsunuz gibi kontrolleri yapar. Bytecode verifieri bi nevi polis olarak düşünün adam hatalı bir şey gördü mü tokatlıyor cezayı kesiyor.

4) Interpreter(Yorumlayıcı) : "Zoo.class" dosyamızda bulunan bytecode'yi "operand stack + local variables" mantığıyla adım adım çalıştırır. İlk anda JIT (Just In Time) derlemesi yoktur, yorumlayıcı başlar. Yorumlayıcıyı zorla çalıştırmak istersek :

 

java -Xint Hello

Bu modda program genelde daha yavaş olur. Çünkü her bytecode adım adım yorumlanır.

 

5) Just-In-Time (JIT) / Runtime : JVM çok sık çalıştırılan (hot) metotları tespit eder, sona JIT devreye girer ve bu metotları yerel makine kodlarına derler.

Derleme anlarını Konsolda göstermek istersek:

java -XX:+PrintCompilation Zoo

 

 

Ve burda GC (Garbage Collector)'da çalışır artık erişilemeyen nesneleri siler, belleği geri kazanılır.

 

java -Xms64m -Xmx64m -Xlog:gc* Zoo

 

Ayrıca bu Runtime kısmında Threadler, Hataların (Exception) fırlatılması, native (JNI) çağrıları bu aşamada yer alır.

 

6) Hardware (Donanım) : Artık burada JIT'nin ürettiği makine kodu, doğrudan cpu'ya gider ve çalışır bu sayede bytecode artık portable özelliğini korur.