Anladığım kadarıyla, Java'da yığın bellek ilkelleri ve yöntem çağırmalarını tutar ve nesneleri saklamak için yığın belleği kullanılır.
Bir dersim olduğunu varsayalım
class A { int a ; String b; //getters and setters }
a sınıfındaki
A ilkeli nerede saklanacak?
Neden yığın bellek var? Neden her şeyi yığın üzerinde saklayamıyoruz?
Nesne çöp toplandığında, itiraz edilenle ilişkili yığın yok edilir mi?
Yığın ve yığın arasındaki temel fark, değerlerin yaşam döngüsüdür.
Yığın değerleri yalnızca içinde oluşturuldukları işlev kapsamında bulunur. Döndükten sonra atılırlar.
Öbek üzerinde öbek değerleri var. Zaman içinde bir noktada oluşturulurlar ve başka bir yerde yok edilirler (dile/çalışma süresine bağlı olarak GC veya manuel olarak).
Şimdi Java yığın üzerinde sadece ilkelleri depolar.
Öbek üzerinde nesneler oluşturulur ve yalnızca referanslar (sırayla ilkeldir) yığın üzerinde aktarılır.
Böylece, bir nesne oluşturursanız, o nesneye ait tüm değişkenlerle birlikte yığına konulur, böylece işlev çağrısı döndükten sonra da devam edebilir.
Temel alanlar, bir yerde başlatılan nesnenin bir parçası olarak saklanır. Bunun nerede olduğunu düşünmenin en kolay yolu yığıntır. Ancak , durum her zaman böyle değildir. Java teorisi ve uygulaması: Kentsel performans efsaneleri, yeniden ziyaret edildi :
JVM'ler kaçış analizi adı verilen bir teknik kullanabilir, bu sayede belirli nesnelerin tüm kullanım ömürleri boyunca tek bir iş parçacığına bağlı kaldıklarını ve yaşam sürelerinin belirli bir yığın çerçevesinin yaşam süreleriyle sınırlandığını söyleyebilirler. Bu tür nesneler yığın yerine yığına güvenle tahsis edilebilir. Daha da iyisi, küçük nesneler için JVM tahsisi tamamen optimize edebilir ve nesnenin alanlarını kayıtlara çekebilir.
Bu nedenle, "nesne yaratılır ve alan da oradadır" demenin ötesinde, yığın üzerinde veya yığın üzerinde bir şey olup olmadığı söylenemez. Küçük, kısa ömürlü nesneler için, 'nesnenin' bellekte bu şekilde mevcut olmayabileceğini ve bunun yerine alanlarının doğrudan kayıtlara yerleştirilebileceğini unutmayın.
Bildiri şu şekilde sonuçlanmaktadır:
JVM'ler, yalnızca geliştiricinin bildiğini varsaydığımız şeyleri anlamada şaşırtıcı derecede iyi. JVM'nin duruma göre yığın tahsisi ve yığın tahsisi arasında seçim yapmasına izin vererek, programcıyı yığın üzerinde mi yoksa yığın üzerinde mi tahsis edileceğinden rahatsız etmeden yığın tahsisinin performans avantajlarından yararlanabiliriz.
Dolayısıyla, şuna benzeyen bir kodunuz varsa:
void foo(int arg) { Bar qux = new Bar(arg); ... }
...,
qux'nin bu kapsamdan çıkmasına izin vermezse,
qux atanabilir yerine yığını. Bu aslında VM için bir kazançtır, çünkü çöp toplanması gerekmediği anlamına gelir - kapsamdan ayrıldığında yok olur.
Daha fazla bilgi kaçış analizi Wikipedia'da. Makaleleri incelemek isteyenler için, Java için Escape Analysis IBM'den. C # dünyasından gelenler için, Yığın Bir Uygulama Detayıdır ve Değer Türleri Hakkındaki Gerçek Eric Lippert'in iyi okumalarını bulabilirsiniz (Java türleri de çoğu kavram ve yön aynı veya benzerdir). .Net kitapları neden yığın ve yığın bellek ayırma hakkında konuşuyor? da buna giriyor.
Peki, neden yığın veya yığın var? Kapsamı bırakan şeyler için yığın pahalı olabilir. Kodu düşünün:
void foo(String arg) { bar(arg); ... } void bar(String arg) { qux(arg); ... } void qux(String arg) { ... }
Parametreler yığının bir parçasıdır. Bir yığınınız yoksa, yığındaki tüm değer kümesini geçiriyor olursunuz. Bu
"foo" Ve küçük dizeler için iyidir ... ancak birisi o dizeye büyük bir XML dosyası koyarsa ne olur? Her çağrı, tüm büyük dizeyi yığına kopyalar - ve oldukça boşa gider.
Bunun yerine, yaşamı olan nesneleri yakın kapsamın dışına (başka bir kapsama geçen, başkalarının bakımını yaptığı bir yapıya yapışan, vb.) Yığın olarak adlandırılan başka bir alana koymak daha iyidir.
Yığına ihtiyacınız yoktur. Varsayımsal olarak, yığın kullanmayan bir dil (keyfi derinlikte) yazılabilir. Gençliğimde öğrendiğim eski bir BASIC bunu yaptı, sadece 8 seviyeli
gosub çağrısı yapabilirdi ve tüm değişkenler küreseldi - yığın yoktu.
Yığının avantajı, bir kapsamda var olan bir değişkeniniz olduğunda, o kapsamdan ayrıldığınızda, o yığın çerçevesinin açılmış olmasıdır. Orada olanı ve olmayanı gerçekten basitleştirir. Program başka bir prosedüre, yeni bir yığın çerçevesine geçer; program prosedüre geri döner ve mevcut kapsamınızı gören programa geri dönersiniz; program yordamı terk eder ve yığındaki tüm öğeler yeniden konumlandırılır.
Bu, kodun bir yığın ve yığın kullanması için çalışma zamanını yazan kişi için hayatı gerçekten kolaylaştırır. Sadece kod üzerinde çalışan birçok kavram ve yol, dilde kod yazan kişinin bunları açıkça düşünmekten kurtulmasını sağlar.
Yığının doğası da parçalanamayacağı anlamına gelir. Bellek parçalanması yığınla ilgili gerçek bir sorundur. Birkaç nesne ayırırsınız, daha sonra çöp orta bir tane toplar ve sonra bir sonraki büyük nesneye yer ayırmaya çalışırsınız. Bu bir karmaşa. Bunun yerine yığına bir şey koymak, bununla başa çıkmak zorunda olmadığınız anlamına gelir.
Bir şey çöp toplandığında, gitti. Ancak, sadece unutulduğu için toplanan çöptür - programdaki mevcut durumdan erişilebilen programdaki nesneye daha fazla referans yoktur.
Bunun çöp toplamada çok büyük bir basitleştirme olduğuna dikkat çekeceğim. Birçok çöp toplayıcı vardır (Java içinde bile - çeşitli bayraklar kullanarak çöp toplayıcısını değiştirebilirsiniz ( dokümanlar ). Bunlar farklı davranır ve her birinin bir şeyleri nasıl yaptığını inceler Bu yanıt için biraz fazla derin.Bunun nasıl çalıştığı hakkında daha iyi bir fikir edinmek için Java Garbage Collection Basics bölümünü okumak isteyebilirsiniz.
Bununla birlikte, yığına bir şey tahsis edilirse,
System.gc() parçası olarak toplanan çöp değildir - yığın çerçevesi açıldığında yeniden konumlandırılır. Öbek üzerinde bir şey varsa ve yığındaki bir şeyden bahsediliyorsa, o zaman çöp toplanmaz.
Çoğunlukla, geleneği. Yazılan ders kitapları ve derleyici sınıfları ve çeşitli bit dokümanları yığın ve yığın hakkında önemli şeyler yapar.
Ancak, günümüzün sanal makineleri (JVM ve benzeri) bunu programcıdan gizli tutmaya çalışmak için büyük çaba sarf etmiştir. Birinden veya diğerinden kalmadıysanız ve neden (depolama alanını uygun şekilde arttırmak yerine) bilmeniz gerekmedikçe, bu da önemli değil çok.
Nesne bir yerdedir ve onun bulunduğu uygun süre boyunca doğru ve hızlı bir şekilde erişilebildiği yerdir. Yığında veya yığın üzerinde ise - gerçekten önemli değil.
Java), kaçış analizi yoluyla bunun anlambilimi etkilemeyeceğini kanıtladıktan sonra sınıf örneğini yığın üzerinde bir optimizasyon olarak tahsis etmezse, bu bir uygulama detayıdır, ancak mikro-optimizasyon cevabı "öbek üzerinde".
Yığın belleği, son giren ilk çıkar sırasında tahsis edilmeli ve yeniden yerleştirilmelidir. Yığın bellek herhangi bir sırada tahsis edilebilir.
Nesne çöp toplandığında, yığından ona işaret eden başka referans yoktur. Eğer olsaydı, nesneyi canlı tutacaklardı. Yığın ilkelleri hiç çöp toplanmaz, çünkü işlev döndüğünde otomatik olarak yok edilirler.
Yığın belleği, yerel değişkenleri ve fonksiyon çağrısını saklamak için kullanılır.
Yığın bellek nesneleri Java'da saklamak için kullanılır. Olursa olsun, kodda nesne nerede oluşturulur.
ailkeli
class Asaklanabilir?
Bu durumda, ilkel a, A sınıfı nesne ile ilişkilidir. Yani Yığın Belleğinde yaratır.
Neden yığın bellek var? Neden her şeyi yığın üzerinde saklayamıyoruz?
Nesne çöp toplandığında, itiraz edilenle ilişkili yığın yok edilir mi?
Çöp Toplayıcı, Yığın bellek kapsamında çalışır, bu nedenle referans zinciri olmayan nesneleri kökten yok eder.