yoklateknik mülakat

Backend Java Memory Jvm Mülakat Soruları

75 doğrulanmış Backend Java Memory Jvm mülakat sorusu — cevaplarıyla çöz, açıklamalarıyla öğren, gerçek simülasyonda kendini test et.

Gerçek simülasyonu dene →

Örnek sorular

Java Memory JvmZorluk 1
public class Demo {
    public static void main(String[] args) {
        int x = 5;
        Point p = new Point(1, 2);
    }
}

class Point {
    int x, y;
    Point(int x, int y) { this.x = x; this.y = y; }
}

x yerel değişkeni ve p'nin referans ettiği Point nesnesi JVM'in bellek alanlarında nerede yaşar?
  • aHem x hem Point nesnesi heap'te yaşar; yalnızca p'nin kendisi stack frame'inde yaşar
  • bx ve p stack frame'de durur; yalnızca Point nesnesi heap'te yaşar
  • cHem x hem Point nesnesi main'in stack frame'i içinde yaşar
  • dx heap'te yaşar, Point nesnesi ve p ise ikisi de stack'te yaşar
Açıklama:Her thread'in, aktif her metod çağrısı için bir frame'den oluşan kendi stack'i vardır. x gibi primitive yerel değişkenler doğrudan o anki frame içinde saklanır. p gibi referans değişkenler de frame içinde saklanır, ama işaret ettikleri nesne -- burada new ile oluşturulan Point instance'ı -- tüm thread'lerin erişebildiği paylaşılan heap'te tahsis edilir. main döndüğünde frame (ve x, p) kaybolur, ama Point nesnesi yalnızca artık hiçbir şey ona referans vermediğinde ve garbage collector onu geri kazandığında yok olur.
Java Memory JvmZorluk 2
String a = "hello";
String b = "hello";
System.out.println(a == b);

Bu ne yazdırır ve neden?
  • afalse, çünkü == her zaman nesne kimliğini karşılaştırır ve string literal'ler asla paylaşılmaz
  • bfalse, çünkü her String literal'i heap'te yeni bir nesne tahsis eder
  • ctrue, ama yalnızca JIT derleyicisi tesadüfen bu belirli örüntüyü optimize ettiği için
  • dtrue, çünkü her iki literal de string pool'da aynı girdiye intern edilir
Açıklama:String literal'ler JVM tarafından otomatik olarak intern edilir: sınıf yüklendiğinde "hello" string pool'a bir kez yerleştirilir ve aynı ya da başka bir sınıftaki bu literal'in her tekrarı yeni bir nesne tahsis etmek yerine o havuzlanmış aynı String nesnesini yeniden kullanır. a ve b ikisi de o tek havuzlanmış nesneye referans verdiğinden, == (kimlik karşılaştırması) true döner. Bu, literal'ler için bir JIT optimizasyonu değil JVM seviyesinde bir garantidir ve tam olarak bu yüzden ==, çalışma zamanında kurulan string'leri karşılaştırmak için güvenilmezdir.
Java Memory JvmZorluk 2
String a = "hello";
String b = new String("hello");
System.out.println(a == b);
System.out.println(a.equals(b));

Sırayla ne yazdırılır?
  • aÖnce false, sonra true
  • bÖnce true, sonra true
  • cÖnce false, sonra false
  • dÖnce true, sonra false
Açıklama:new String("hello"), karakterleri havuzlanmış literal'den kopyalansa bile, heap'te yepyeni bir String nesnesinin tahsis edilmesini açıkça zorlar -- bu nesne asla otomatik olarak string pool'a eklenmez. Bu yüzden a (havuzlanmış literal) ve b (taze tahsis edilen kopya) farklı nesnelerdir, a == b false olur. equals kimlik yerine karakter içeriğini karşılaştırır ve her iki string de aynı karakterleri taşıdığından a.equals(b) true olur. Bu iki satır, String için kimlik karşılaştırması ile değer karşılaştırmasının neden birbirinin yerine geçmediğinin klasik göstergesidir.
Java Memory JvmZorluk 1
Bir Java programı StackOverflowError ile çöküyor. Aslında neyin tükendiğini en iyi hangisi açıklar?
  • aHeap, yeni nesneler tahsis etmek için yer tükendi
  • bJVM, işletim sisteminin native thread'lerini tüketti
  • cBir thread'in call stack'i, derin recursion yüzünden sabit boyutunu aştı
  • dGarbage collector zamanında yeterince erişilemez nesneyi serbest bırakamadı
Açıklama:StackOverflowError, özellikle tek bir thread'in call stack'inin -- her aktif metod çağrısı için bir frame tutan bölgenin -- yapılandırılmış boyutunu aştığı anlamına gelir; bu neredeyse her zaman kontrolsüz ya da aşırı derin recursion yüzündendir (her recursive çağrı, dönmeden yeni bir frame ekler). Bu, heap'ten ayrı bir bellek alanı ve ayrı bir hata biçimidir: OutOfMemoryError: Java heap space, heap'in toplanamayan nesnelerle dolu olduğu anlamına gelir, bu farklı bir çözümü olan farklı bir sorundur.
Java Memory JvmZorluk 2
String s = "a";
for (int i = 0; i < 3; i++) {
    s += i;
}
System.out.println(s);

Döngü içinde her s += i çalıştığında, bellekte String nesnesine ne olur ve neden?
  • as'in referans ettiği mevcut String nesnesi, yeni karakteri eklemek için yerinde değiştirilir; hep tek bir String nesnesi var olur
  • bString immutable olduğu için, s += i her iterasyonda yeni bir String nesnesi oluşturur (eski içerik i ile birleştirilmiş halde); s'in önceki referans ettiği nesne erişilemez hale gelip çöp olur; döngü sonunda yol boyunca birkaç atılmış ara String nesnesi oluşmuş olur
  • cJVM bu döngüyü her zaman tüm iterasyonlar boyunca tek bir StringBuilder çağrısı kullanacak şekilde yeniden yazar, bu yüzden döngü kaç kere çalışırsa çalışsın en fazla bir ara nesne oluşur
  • ds += i yalnızca döngünün ilk çalışmasında yeni bir nesne ayırır; sonraki iterasyonlar Java dizileri yeniden boyutlandırılabilir olduğu için aynı alttaki karakter dizisini yeniden kullanır
Açıklama:Java String nesneleri immutable'dır -- String üzerindeki hiçbir metot zaten tuttuğu karakterleri değiştiremez. Derleyiciler genelde tek bir + ifadesini verimlilik için dahili bir buffer tabanlı çağrıya çevirir, ama bu optimizasyon her concatenation ifadesi için ayrı ayrı uygulanır; ayrı döngü iterasyonlarını tek bir accumulator'da birleştirmez, çünkü s her iterasyonda yeni bir referansa atanır. Yani her s += i, birleşik karakterleri tutan yeni bir String nesnesi üretir ve s'in önceden işaret ettiği nesne garbage collection'a uygun hale gelir. Çok sayıda iterasyon boyunca tekrarlanan concatenation için tek bir StringBuilder kullanıp .append() çağırmak, tüm bu ara nesnelerin oluşturulup atılmasını önler.
Java Memory JvmZorluk 3
Bir junior geliştirici, try-with-resources kullanmak yerine, bir nesne garbage collect edildiğinde dosya handle'ını kapatmak için finalize()'ı override etmeye güveniyor. Bu yaklaşımın temel sorunu nedir?
  • aGC, finalize()'ın ne zaman/çalışıp çalışmayacağına karar verir, temizlik zamanlaması öngörülemez
  • bfinalize(), bir referans scope dışına çıktığı anda senkron biçimde çağrılır, bu da çağıran thread'i bloklayabilir
  • cfinalize() yalnızca AutoCloseable'ı da implemente eden sınıflarda kullanılabilir
  • dfinalize()'ı override eden nesneler otomatik olarak garbage collection'a uygun olmaktan çıkar
Açıklama:Kaynak temizliği için finalize()'a güvenmek güvenilmezdir çünkü JVM, finalize()'ın ne zaman -- hatta çalışıp çalışmayacağı -- konusunda hiçbir söz vermez; bu tamamen garbage collector'ın bir nesneyi ne zaman (ya da hiç) erişilemez sayıp finalizasyonu zamanladığına bağlıdır, bu da kaynağın serbest bırakılması gerekenden çok sonra olabilir, ya da JVM önce çıkarsa hiç olmayabilir. Buna karşılık try-with-resources, blok çıktığı anda close()'u deterministik biçimde çağırır, bu yüzden dosya handle'ı ya da soket gibi işletim sistemi seviyesinde bir kaynak tutan her şey için önerilen örüntüdür.

3300 soruluk Backend bankasında kendini sına.

Mülakata başla