Java'nın boolean ilkel boyutu neden tanımlanmadı?


111

Java Sanal Makinesi Şartname boolean için sınırlı destek olduğunu söylüyor ilkel türleri.

Yalnızca boole değerleri üzerindeki işlemlere ayrılmış hiçbir Java sanal makine talimatı yoktur. Bunun yerine, Java programlama dilindeki boole değerlerinde çalışan ifadeler, Java sanal makine int veri türünün değerlerini kullanmak için derlenir.

Yukarıdakiler (yanlış yorumlamış olsam da), mantıksal değerlerde çalışırken int veri türünün kullanıldığını ima eder, ancak bu 32 bitlik bir bellek yapısıdır. Bir booleanın yalnızca 1 bitlik bilgiyi temsil ettiği göz önüne alındığında:

  • Neden bir bayt veya kısa bir tür, int yerine boole için vekil olarak kullanılmıyor?
  • Herhangi bir JVM için, bir boole türünü depolamak için tam olarak ne kadar bellek kullanıldığını bulmanın en güvenilir yolu nedir?

Yanıtlar:


116

Kısa cevap: evet, boole değerleri 32 bitlik varlıklar olarak işlenir, ancak boole dizileri öğe başına 1 bayt kullanır.

Daha uzun yanıt: JVM, yerel değişkenleri, yöntem argümanlarını ve ifade değerlerini tutmak için kullanılan 32 bitlik bir yığın hücre kullanır. 1 hücreden daha küçük olan temel öğeler doldurulur, 32 bitten büyük (uzun ve çift) temel öğeler 2 hücre alır. Bu teknik, işlem kodlarının sayısını en aza indirir, ancak bazı özel yan etkilere sahiptir (baytları maskeleme ihtiyacı gibi).

Dizilerde depolanan ilkel öğeler 32 bitten daha azını kullanabilir ve bir diziden ilkel değerleri yüklemek ve depolamak için farklı işlem kodları vardır. Boole ve bayt değerlerinin her ikisi de baloadve bastoreişlem kodlarını kullanır; bu, boole dizilerinin öğe başına 1 bayt alması anlamına gelir.

Bellek içi nesne düzeni söz konusu olduğunda, bu "özel uygulama" kuralları kapsamındadır , 1 bit, 1 bayt olabilir veya 64 bitlik çift sözcük sınırına hizalanmış başka bir posterde belirtildiği gibi olabilir. Büyük olasılıkla, temel alınan donanımın temel kelime boyutunu (32 veya 64 bit) alır.


Booleanların kullandığı alan miktarını en aza indirgemeye gelince: bu, çoğu uygulama için gerçekten bir sorun değil. Yığın çerçeveleri (yerel değişkenleri ve yöntem argümanlarını tutan) çok büyük değildir ve büyük şemada bir nesnedeki ayrı bir boole de o kadar büyük değildir. Çok sayıda boole içeren çok sayıda nesneniz varsa, alıcılarınız ve ayarlayıcılarınız aracılığıyla yönetilen bit alanlarını kullanabilirsiniz. Bununla birlikte, CPU süresinde muhtemelen bellekteki cezadan daha büyük bir ceza ödersiniz.


Boolean / bayt sınıfı üyeleri için de 4 bayt oldukları da doğru mu? Sınıf örneği yığın üzerinde bir bütün olarak ayrılmıştır, bu yüzden tahmin edebiliyorum, JVM muhtemelen boolean / bayt üye başına 1 bayt kullanmalı ve sonunda tüm sınıf örneği için 4 baytlık bir hizalama yapmalıdır. Öyle mi? (Bunu kanıtlayan referanslarınız varsa lütfen paylaşın)
dma_k

@dma_k: Cevabımda belirtildiği gibi, bir sınıf örneğinin düzeni uygulamaya bağlıdır. Ancak, sınıf örneklerinin yığında depolanmadığını, yığın üzerinde depolandıklarını unutmayın (nesneleri yığından öbeğe taşıyan JDK 7 "kaçış analizi" için bazı referanslar görseniz de, durum böyle görünmüyor; bkz.
java.sun.com/javase/7/docs/technotes/guides/vm/…

1
Bazen boole'leri paketlemek aslında daha hızlı olabilir. Önbellek boyutu ne zaman önemli olursa, bir şeyler paketlemek daha iyi olabilir. Örneğin, bölümlere ayrılmış bir ana elek, 32 kB'lik (L1 önbellek boyutu) parçalar halinde çalışır, bölümlenmemiş bir süzgeçten çok daha hızlıdır. Parçalar arasında bazı ek yükler vardır ve paketleme ile genel giderleri sekiz kat daha az ödersiniz. Henüz ölçmedim.
maaartinus 01

7

Miras hiyerarşisinde bir yerde tek bir boole, 8 bayta kadar kullanabilir! Bu, dolgudan kaynaklanmaktadır. Java nesnem tarafından ne kadar bellek kullanılıyor? Bölümünde daha fazla ayrıntı bulunabilir. :

Bir booleanın ne kadar tükettiği sorusuna geri dönersek, evet en az bir bayt tüketir, ancak hizalama kuralları nedeniyle çok daha fazlasını tüketebilir. IMHO Bir booleanın [] giriş başına bir bayt tüketeceğini ve bir bitin yanı sıra hizalama ve dizinin boyut alanı için biraz ek yük tüketeceğini bilmek daha ilginçtir. Büyük bit alanlarının yararlı olduğu grafik algoritmaları vardır ve bir boole [] kullanırsanız, gerçekten gerekenden neredeyse tam olarak 8 kat daha fazla belleğe (1 bayta karşılık 1 bayt) ihtiyacınız olduğunu bilmeniz gerekir.


Yine de boole [] nasıl kullanılır?
Thomas Jung

boolean [] bir maske için kullanılabilir. Bazen bir BitSet daha iyi olabilir, çünkü bazı yararlı yöntemleri vardır.
Michael Munsey

5

Özet olarak Java'nın 5. Sürümü (O'Reilly), ilkel boole türünün 1 bayt olduğunu söylüyor. Yığının incelemesinin gösterdiği şeye bağlı olarak bu yanlış olabilir. Çoğu JVM'nin değişkenler için bir bayttan daha az ayırma ile ilgili sorunları olup olmadığını merak ediyorum.


3

Boole eşleme, 32 bit CPU göz önünde bulundurularak yapıldı. İnt değerinin 32 biti vardır, bu nedenle tek bir işlemde işlenebilir.

İşte boyutu ölçmek için Peter Norvig'in Java IAQ'sundan bir çözüm : Nadiren Yanıtlanan Sorular (biraz kesinlik olmadan):

static Runtime runtime = Runtime.getRuntime();
...
long start, end;
Object obj;
runtime.gc();
start = runtime.freememory();
obj = new Object(); // Or whatever you want to look at
end =  runtime.freememory();
System.out.println("That took " + (start-end) + " bytes.");

Bu konuşma ilkellerle ilgili olduğundan, bunu test etmede yaratıcı olmalısınız çünkü ilkeller, bir örnek veya dizide bir alan olmadıkları sürece yığın içinde depolanmaz. Ve bunların hiçbiri Java'nın onu yığında nasıl saklamayı seçeceği sorusuna cevap vermiyor.
Jesse

2

CPU'lar belirli bir veri türü uzunluğunda çalışır. 32bit CPU'lar söz konusu olduğunda bunlar 32 bit uzunluğundadır ve bu nedenle Java'da "int" dediğiniz şeydir. CPU onu işlemeden önce bu uzunluğa kadar doldurulmalı veya bölünmelidir. Bu fazla zaman almaz, ancak temel işlemler için 1 yerine 2 CPU döngüsüne ihtiyacınız varsa, bu maliyet / zamanın iki katına çıkması anlamına gelir.

Bu özellik, yerel veri türleriyle boole'leri işleyebilmeleri için 32 bit CPU'lara ayrılmıştır.

Burada sadece bir tane olabilir: hız veya hafıza - SUN hıza karar verdi.


1

Sun Java eğitimleri, Boolean'ın bir bitlik bilgiyi temsil ettiğini, ancak "boyutunun" kesin olarak tanımlanmış bir şey olmadığını söylüyor. Boole değişmez değerleri, doğru ve yanlış olan yalnızca iki olası değere sahiptir. Ayrıntılar için Java Veri Türlerine bakın.


-10

Neden böyle bir .java dosyası yapmıyorsunuz:

Empty.java

class Empty{
}

ve bunun gibi bir sınıf:

NotEmpty.java

class NotEmpty{
   boolean b;
}

İkisini de derleyin ve .class dosyalarını bir onaltılık düzenleyici ile karşılaştırın.


5
bu, bellekteki ilkel boole türünü boyutlandırmakla ilgisi olmayan, tamamen başka bir metriktir.
Joel
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.