Java'da statik ayırma - yığın, yığın ve kalıcı oluşturma


117

Son zamanlarda java'da bellek ayırma şemaları hakkında çok şey okudum ve çeşitli kaynaklardan okuduğum için birçok şüphem oldu. Kavramlarımı topladım ve tüm noktaları gözden geçirip onlar hakkında yorum yapmayı rica ediyorum. Bellek tahsisinin JVM'ye özgü olduğunu öğrendim, bu yüzden önceden söylemeliyim ki sorum Sun'a özgü.

  1. Sınıflar (sınıf yükleyiciler tarafından yüklenen) yığın üzerinde özel bir alana gider: Kalıcı Üretim
  2. Sınıfın adı, sınıfla ilişkili Object dizileri, JVM tarafından kullanılan dahili nesneler (java / lang / Object gibi) ve optimizasyon bilgileri gibi bir sınıfa ilişkin tüm bilgiler Kalıcı Üretim alanına gider.
  3. Tüm statik üye değişkenler tekrar Kalıcı Üretim alanında tutulur.
  4. Nesneler farklı bir yığın halinde ilerler: Genç nesil
  5. Statik veya statik olmayan her sınıf için her yöntemin yalnızca bir kopyası vardır. Bu kopya Daimi Üretim alanına konur. Statik olmayan yöntemler için, tüm parametreler ve yerel değişkenler yığına gider ve bu yöntemin somut bir çağrısı olduğunda, onunla ilişkilendirilmiş yeni bir yığın çerçevesi elde ederiz. Statik bir yöntemin yerel değişkenlerinin nerede depolandığından emin değilim. Permanent Generation yığınında mı? Veya sadece referansları Kalıcı Üretim alanında saklanır ve asıl kopya başka bir yerde (Nerede?)
  6. Ayrıca bir yöntemin dönüş türünün nerede saklandığından da emin değilim.
  7. Nesnelerin (genç nesilde) statik bir üye kullanması gerekiyorsa (kalıcı nesilde), onlara statik üyeye bir referans verilir ve onlara yöntemin dönüş türünü saklamak için yeterli bellek alanı verilir, vb.

Bunu yaptığın için teşekkürler!

Yanıtlar:


152

Birincisi, şimdiye kadar açık olması gerektiği gibi, bu cevapları ilk elden bilgiyle doğrulayabilecek çok az insan var. Çok az kişi son HotSpot JVM'leri üzerinde çalıştı veya bunları gerçekten bilmek için gereken derinliğe kadar inceledi. Buradaki çoğu insan (ben de dahil), başka bir yerde yazdıklarını gördükleri veya çıkardıkları şeylere dayanarak cevap veriyor. Genellikle burada veya çeşitli makaleler ve web sayfalarında yazılanlar, kesin olabilecek veya olmayabilecek diğer kaynaklara dayanmaktadır. Çoğu zaman basitleştirilmiş, yanlış veya tamamen yanlıştır.

Cevaplarınızın kesin olarak doğrulanmasını istiyorsanız, gerçekten OpenJDK kaynak kodunu indirmeniz ve kaynak kodunu okuyup anlayarak kendi araştırmanızı yapmanız gerekir . SO ile ilgili sorular sormak veya rastgele web makaleleri aracılığıyla gezinmek, sağlam bir akademik araştırma tekniği değildir.

Bunu söyledikten sonra ...

... sorum Güneş'e özgü.

Bu soru sorulduğu sırada, Sun Microsystems ortadan kalkmıştı. Bu nedenle soru Oracle'a özeldi. AFAIK, tüm mevcut (araştırma dışı) 3. taraf JVM uygulamaları ya bir OpenJDK sürümünün doğrudan bağlantı noktalarıdır ya da başka bir Sun / Oracle sürümünden gelmektedir.

Aşağıdaki yanıtlar Oracle Hotspot ve OpenJDK sürümleri ve muhtemelen GraalVM dahil diğerlerinin çoğu için geçerlidir.

1) Sınıflar (sınıf yükleyiciler tarafından yüklenen) yığın üzerinde özel bir alana gider: Permanent Generation.

Java 8'den önce evet.

Java 8'den itibaren PermGen alanı Metaspace ile değiştirildi. Yüklenmiş ve JIT tarafından derlenmiş sınıflar şimdi oraya gidiyor. PermGen artık mevcut değil.

2) Sınıfın adı, sınıfla ilişkili Object dizileri, JVM tarafından kullanılan dahili nesneler (java / lang / Object gibi) ve optimizasyon bilgileri gibi bir sınıfa ilişkin tüm bilgiler Kalıcı Üretim alanına girer.

Az ya da çok, evet. Bunlardan bazılarıyla ne demek istediğinden emin değilim. "JVM tarafından kullanılan dahili nesnelerin (java / lang / Object gibi)" JVM-dahili sınıf tanımlayıcıları anlamına geldiğini tahmin ediyorum.

3) Tüm statik üye değişkenleri tekrar Kalıcı Üretim alanında tutulur.

Değişkenlerin kendileri evet. Bu değişkenler (tüm Java değişkenleri gibi) ya ilkel değerleri ya da nesne referanslarını tutacaktır. Bununla birlikte, statik üye değişkenler permgen yığınında tahsis edilen bir çerçeve içindeyken, bu değişkenler tarafından atıfta bulunulan nesneler / diziler herhangi bir yığın içinde tahsis edilebilir .

4) Nesneler farklı bir yığın halinde ilerler: Genç nesil

Şart değil. Büyük nesneler , doğrudan kullanım hakkına sahip nesile tahsis edilebilir .

5) Statik veya statik olmayan olmak üzere, sınıf başına her yöntemin yalnızca bir kopyası vardır. Bu kopya Daimi Üretim alanına konur.

Yöntemin koduna atıfta bulunduğunuzu varsayarsak, AFAIK evet. Yine de biraz daha karmaşık olabilir. Örneğin bu kod, JVM'nin ömrü boyunca farklı zamanlarda bayt kodu ve / veya yerel kod formlarında bulunabilir.

... Statik olmayan yöntemler için, tüm parametreler ve yerel değişkenler yığına gider - ve bu yöntemin somut bir çağrısı olduğunda, onunla ilişkili yeni bir yığın çerçevesi elde ederiz.

Evet.

... Statik bir yöntemin yerel değişkenlerinin nerede depolandığından emin değilim. Permanent Generation yığınında mı? Veya sadece referansları Kalıcı Üretim alanında saklanır ve asıl kopya başka bir yerde (Nerede?)

Hayır. Statik olmayan yöntemlerdeki yerel değişkenler gibi yığın üzerinde depolanırlar.

6) Ayrıca bir yöntemin dönüş türünün nerede saklandığından da emin değilim.

Bir (geçersiz olmayan) yöntem çağrısı tarafından döndürülen değeri kastediyorsanız , ya yığında ya da bir makine kaydında döndürülür. Yığın üzerinde döndürülürse, dönüş türüne bağlı olarak bu 1 veya iki kelime alır.

7) Nesneler (genç nesilde) statik bir üye kullanmak isterse (kalıcı nesil), statik üyeye bir referans verilir ve onlara yöntemin dönüş türünü depolamak için yeterli bellek alanı verilir, vb. .

Bu yanlıştır (ya da en azından kendinizi açıkça ifade etmiyorsunuz).

Bazı yöntemler statik bir üye değişkene erişirse, aldığı şey ya ilkel bir değer ya da bir nesne başvurusudur . Bu, (mevcut) bir yerel değişkene veya parametreye atanabilir, (mevcut) statik veya statik olmayan üyeye atanabilir, önceden tahsis edilmiş bir dizinin (mevcut) bir öğesine atanabilir veya basitçe kullanılabilir ve atılabilir.

  • Hiçbir durumda, bir referans veya ilkel değeri tutmak için yeni bir depolama alanı tahsis edilmesine gerek yoktur .

  • Tipik olarak, bir nesne veya dizi referansını saklamak için gereken tek şey bir bellek kelimesidir ve ilkel bir değer, donanım mimarisine bağlı olarak tipik olarak bir veya iki kelimeyi kaplar.

  • Hiçbir durumda, bir yöntem tarafından döndürülen bazı nesnelerin / dizilerin tutulması için çağıran tarafından yer ayrılmasına gerek yoktur. Java'da nesneler ve diziler her zaman değerine göre geçiş semantiği kullanılarak döndürülür ... ancak döndürülen bu değer bir nesne veya dizi başvurusudur.


Daha fazla bilgi için lütfen şu kaynaklara bakın:

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.