Java'da bir boole değişkeninin boyutu nedir?


89

Java'da boole'nin bit boyutunu bilen var mı?


Yanıtlar:


41

Sanal makineye bağlıdır.


9
Bazı belgelere işaret etmek ister misin? Bir boolean boyutunun makineye bağlı olduğuna inanmakta zorlanıyorum. Bu, boole içeren bir sınıfın ikili temsilinin farklı VM'de farklı boyutlara (ve bellek düzenlerine) sahip olacağı ve bu, VM'lerin uyumlu olmayacağı anlamına gelir.
David Rodríguez - dribeas

14
Sanırım sorunun, bir sınıf dosyasında kodlanmış bir boole değişkeninin boyutuna değil, bellekteki bir boole değişkeninin boyutuna atıfta bulunduğu ima edildi. Bellekteki boyut, Sun'ın belgelerine göre VM'ye göre değişir. Sınıf dosyasındaki boyut sabittir.
William Brendel

3
@ DavidRod Rodríguez-dribeas - Java 1.1 zamanında Sun JVM, bir örnek veya otomatik değişken olarak depolandığında boole için 4 bayt kullandı. Bu, bayt kodu yorumlayıcısının uygulanmasını basitleştirdi (bool'ları yığın üzerinde 4 bayt kaplıyor olarak kabul eder) ve en az dirençli yoldur. İSeries "Classic" JVM'yi uyguladığımızda, örnek değişkenlerini 1 bayt yapmanın yollarını bulduk, çünkü bu, bazı nesnelerin kompaktlığını büyük ölçüde geliştirdi (bu, performans üzerinde inanılmaz bir etkiye sahiptir). Görünüşe göre, aşağıdaki gönderilere dayanarak, Sun / Oracle geliştiricileri sonraki sürümlerde aynı şekilde nasıl yapılacağını buldular.
Hot Licks

Ama doğru, 2017'nin sonlarından itibaren JavaDocs şöyle diyor: boolean: The boolean data type... This data type represents one bit of information, but its "size" isn't something that's precisely defined- ama amacınız geçerli, bazı bağlantılar ve daha iyi bilgiler kullanabilir :)
JimLohse

185

Sanal makineye bağlıdır, ancak kodu Java'daki baytlar hakkında sorulan benzer bir sorudan uyarlamak kolaydır :

class LotsOfBooleans
{
    boolean a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af;
    boolean b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf;
    boolean c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf;
    boolean d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df;
    boolean e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef;
}

class LotsOfInts
{
    int a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af;
    int b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf;
    int c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf;
    int d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df;
    int e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef;
}


public class Test
{
    private static final int SIZE = 1000000;

    public static void main(String[] args) throws Exception
    {        
        LotsOfBooleans[] first = new LotsOfBooleans[SIZE];
        LotsOfInts[] second = new LotsOfInts[SIZE];

        System.gc();
        long startMem = getMemory();

        for (int i=0; i < SIZE; i++)
        {
            first[i] = new LotsOfBooleans();
        }

        System.gc();
        long endMem = getMemory();

        System.out.println ("Size for LotsOfBooleans: " + (endMem-startMem));
        System.out.println ("Average size: " + ((endMem-startMem) / ((double)SIZE)));

        System.gc();
        startMem = getMemory();
        for (int i=0; i < SIZE; i++)
        {
            second[i] = new LotsOfInts();
        }
        System.gc();
        endMem = getMemory();

        System.out.println ("Size for LotsOfInts: " + (endMem-startMem));
        System.out.println ("Average size: " + ((endMem-startMem) / ((double)SIZE)));

        // Make sure nothing gets collected
        long total = 0;
        for (int i=0; i < SIZE; i++)
        {
            total += (first[i].a0 ? 1 : 0) + second[i].a0;
        }
        System.out.println(total);
    }

    private static long getMemory()
    {
        Runtime runtime = Runtime.getRuntime();
        return runtime.totalMemory() - runtime.freeMemory();
    }
}

Tekrarlamak gerekirse, bu VM'ye bağlıdır, ancak Sun'ın JDK derlemesi 1.6.0_11 çalıştıran Windows dizüstü bilgisayarımda aşağıdaki sonuçları aldım:

Size for LotsOfBooleans: 87978576
Average size: 87.978576
Size for LotsOfInts: 328000000
Average size: 328.0

Bu, mantıksal değerlerin temelde Sun'un JVM'si tarafından bir bayt olarak paketlenebileceğini gösteriyor.


21
@skeet - Seni gerçekten selamlıyorum. cevabın harika
Warrior

2
@warrior: "Bayt" kodunu zaten aldığım için, onu "boole" olarak değiştirmek oldukça basitti :)
Jon Skeet

3
System.gc (), belleğin temizleneceğini garanti etmez. JVM'ye çöp toplamayı çalıştırması için bir emir verir, ancak toplayıcının gerçekten bir şeyi temizlediği anlamına gelmez. Toplayıcının KULLANILMAYAN nesneleri temizlediğini unutmayın. Program daha fazla başvuruda bulunmazsa nesne kullanılmaz. Bu yüzden, testinizde, gc () çalıştırmadan önce LotsOfBooleans'ı null olarak ayarlayarak referansı açıkça bırakacağım; YA DA sadece bir kez boole ile, bir kez int ile çalıştır ve sonra sayıları karşılaştır.
Randa Sbeity

2
@RandaSbeity Veya daha iyisi: her iki referansı da koruduğunuzdan ve bellek farkını hesapladığınızdan emin olun. Burada olan tam olarak budur.
biziclop

1
Jon Skeet'in cevaplayamayacağı bir soru var mı?
Andreas Hartmann

31

Java'da bir boole değeri ile temsil edilen gerçek bilgi bir bittir: doğru için 1, yanlış için 0. Ancak, bellekteki bir boole değişkeninin gerçek boyutu Java spesifikasyonu tarafından kesin olarak tanımlanmamıştır. Java'daki İlkel Veri Türlerine bakın .

Boolean veri türünün yalnızca iki olası değeri vardır: true ve false. Doğru / yanlış koşullarını izleyen basit bayraklar için bu veri türünü kullanın. Bu veri türü bir bitlik bilgiyi temsil eder, ancak "boyutu" kesin olarak tanımlanmış bir şey değildir.


21

Yan notta ...

Bir dizi Boole nesnesi kullanmayı düşünüyorsanız, yapmayın. Bunun yerine bir BitSet kullanın - bazı performans optimizasyonları (ve bir sonraki set / unset biti almanıza izin veren bazı güzel ekstra yöntemler) vardır.


Bu her zaman doğru değildir stackoverflow.com/questions/605226/…
Przemek

Bu yanıt, boole [] kullanmak için önemli nedenler olduğunu gösteriyor, ancak oradaki yorumların da gösterdiği gibi, onu destekleyecek pek bir şey yok. Bunu söyledikten sonra: Java'da fazla program yapmıyorum (ve herhangi bir kanıt da
sunmadım

6

Java'nın bir booleanveri türü için bir bayt ayırdığını, ancak yalnızca bir bit kullandığını okudum . Bununla birlikte, dokümantasyon "boyutunun" kesin olarak tanımlanmış bir şey olmadığını " söylüyor . Buraya bakın.


Bu bir öğretici, 'dokümantasyon' değil. Dokümantasyon JLS, JVM Spec. Ve Javadoc'tur.
Marquis of Lorne

2

booleanDeğerleri derlenmektedir intJVM veri türü. Buraya bakın .


2
Hafızada bu şekilde saklanmaları gerekmez ve bence soruyu soran kişinin bilmek istediği de buydu. Bu belge, uygulamaya bağlı olduğu için bellekteki bir boolean değişkeninin temsilini değil, sınıf dosya formatını (derlenmiş bayt kodu) açıklar.
William Brendel

2

Java'daki boolean boyutu sanal makineye bağlıdır. ancak herhangi bir Java nesnesi 8 baytlık bir ayrıntı düzeyine hizalanır. Bir Boole, toplam 9 bayt bilgi için 8 bayt başlık ve 1 bayt yük içerir. JVM daha sonra onu 8'in sonraki katına yuvarlar, böylece java.lang.Boolean'ın bir örneği 16 bayt bellek kullanır.


Buna katılmıyorum, HotSpot JVM 1.7.0_51'de başlık boole için 12 bayt + 1 + taneciklik için 3'e sahip.
Eugene

14
Boolean ile boolean'ı karıştırmayın.
andresp

1
Bayt mı, bit mi? 16 Bayt büyük bir zaman için çok Booleanisraf olur ... Bu longBoolean
a'nın boyutu a'dan

0

Tanımsız; Jon Skeet'in önerdiği gibi şeyler yapmak, size belirli bir platform hakkında bir yaklaşım getirecektir, ancak belirli bir platform için kesin olarak bilmenin yolu bir profilleyici kullanmaktır.

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.