Javaのブール変数のサイズは?


89

誰でもJava のブール値のビットサイズを知ることができますか?


1
同じですが、ここで尋ねた:stackoverflow.com/questions/1907318/...
dma_k

回答:


41

仮想マシンに依存します。


9
いくつかのドキュメントを指すように注意しますか?ブール値のサイズがマシンに依存しているとは信じがたいです。つまり、ブール値を含むクラスのバイナリ表現は、VMごとにサイズ(およびメモリレイアウト)が異なり、VMに互換性がないことを意味します。
デビッドロドリゲス-ドリベス2008

14
問題は、クラスファイルにエンコードされたブール変数のサイズではなく、メモリ内のブール変数のサイズを参照していることを暗に示していたと思います。メモリのサイズは、SunのドキュメントによるとVMによって異なります。クラスファイルのサイズは一定です。
William Brendel

3
@DavidRodríguez-dribeas-Java 1.1の頃のSun JVMは、インスタンスまたは自動変数として格納されている場合、ブール値に4バイトを使用していました。これにより、バイトコードインタープリターの実装が簡素化され(ブール値はスタック上で4バイトを占有していると見なされます)、抵抗が最も少ない経路でした。iSeriesの「クラシック」JVMを実装すると、インスタンスの変数を1バイトにする方法が見つかりました。これにより、一部のオブジェクトのコンパクトさが大幅に改善されました(パフォーマンスに驚くほどの影響があります)。どうやら、以下の投稿に基づいて、Sun / Oracleの開発者は、以降のバージョンでも同様に行う方法を考え出しました。
Hot Licks 2013

しかし、それは正しい、2017年後半のJavaDocsは言う:boolean: The boolean data type... This data type represents one bit of information, but its "size" isn't something that's precisely defined-しかしあなたのポイントは有効です、それはいくつかのリンクとより良い情報を使用することができます:)
JimLohse

185

それは仮想マシンに依存しますが、Javaのバイトについて尋ねる同様の質問からコードを適応させるのは簡単です

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();
    }
}

繰り返しますが、これはVMに依存しますが、SunのJDKビルド1.6.0_11を実行しているWindowsラップトップでは、次の結果が得られました。

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

つまり、ブール値は基本的にSunのJVMによってそれぞれ1バイトにパックできるということです。


21
@skeet-私は本当にあなたに敬礼します。あなたの答えは素晴らしいです
戦士

2
@warrior:「byte」のコードはすでに取得しているため、「boolean」に変更するのは非常に簡単でした:)
Jon Skeet

3
System.gc()はメモリのクリーニングを保証しません。JVMにガベージコレクションを実行するように命令するだけですが、コレクターが実際に何かをクリーンアップしたという意味ではありません。コレクターが未使用のオブジェクトをクリーンアップすることを忘れないでください。プログラムがオブジェクトへの参照をこれ以上保持しない場合、オブジェクトは使用されません。したがって、テストでは、gc()を実行する前にLotsOfBooleansをnullに設定して、明示的に参照を削除します。または、メインをブールで1回、intで1回実行してから、数値を比較します。
Randa Sbeity、2014年

2
@RandaSbeityまたはそれ以上:両方の参照を保持し、メモリの違いを計算するようにしてください。これがまさにここで起こることです。
biziclop 2015

1
ジョン・スキートが答えられない質問はありますか?
Andreas Hartmann

31

Javaのブール値で表される実際の情報は1ビットです。1はtrue、0はfalseです。ただし、メモリ内のブール変数の実際のサイズは、Java仕様では正確に定義されていません。Javaのプリミティブデータ型を参照してください。

booleanデータ型には、trueとfalseの2つの値しかありません。このデータ型は、true / false条件を追跡する単純なフラグに使用します。このデータ型は1ビットの情報を表しますが、その「サイズ」は正確に定義されたものではありません。


21

余談ですが...

ブールオブジェクトの配列の使用を検討している場合は、使用しないでください。代わりにBitSetを使用してください-いくつかのパフォーマンスの最適化(およびいくつかの素晴らしい追加メソッドがあり、次のセット/セット解除ビットを取得できるようにします)。


これは常に真ではありませんstackoverflow.com/questions/605226/...
Przemek

その回答は、boolean []を使用する重要な理由があることを示唆していますが、そこにあるコメントが示すように、それをバックアップすることはあまりありません。そうは言っても、私はJavaであまりプログラミングしていません(そして証拠も提供していません;)
Matthew Schinckel

6

Javaはbooleanデータ型用に1バイトを予約しているが、1ビットしか使用していないことを読んだ。ただし、ドキュメントには「その「サイズ」は正確に定義されたものではない」と記載されています。 こちらをご覧ください。


これはチュートリアルであり、「ドキュメント」ではありません。ドキュメントは、JLS、JVM仕様、およびJavadocです。
ローンの侯爵

2

boolean値がにコンパイルされているintJVMでのデータ型。こちらをご覧ください


2
それは必ずしもそれらがメモリに保存される方法とは限りません。私は、質問をしている人が知りたかったことだと思います。このドキュメントでは、実装に依存しているため、メモリ内のブール変数の表現ではなく、クラスファイル形式(コンパイル済みバイトコード)について説明しています。
William Brendel

2

Javaのブール値のサイズは仮想マシンに依存します。しかし、どのJavaオブジェクトも8バイトの粒度に調整されます。ブール値には、8バイトのヘッダーと1バイトのペイロードがあり、合計9バイトの情報が含まれます。次に、JVMはそれを次の8の倍数に切り上げます。そのため、java.lang.Booleanの1つのインスタンスが16バイトのメモリを占有します。


HotSpot JVM 1.7.0_51では、ヘッダーに12バイト+ブール値の1 +細分性の3が含まれています。
ユージーン

14
ブールとブールを混同しないでください。
andresp 2015

1
バイトまたはビット?Booleanウォルドの16バイトは無駄です... longこれは、a よりも1兆倍多くの情報を運ぶことができるサイズですBoolean
Dici

0

未定義です。Jon Skeetが提案するようなことを行うと、特定のプラットフォームでの概算が得られますが、特定のプラットフォームについて正確に知る方法は、プロファイラーを使用することです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.