专栏首页做不甩锅的后端在java中boolean类型占多少字节?

在java中boolean类型占多少字节?

近看到一个特别有意思的面试题,就是面试官问boolean占多少字节。一时间还不知道如何回答。我们先来看看java中的基本数据类型。

1.八大基本数据类型

java提供了8大基本数据类型:

数据类型

长度

位数

默认值

byte

1Byte

8

0

short

2Byte

16

0

int

4Byte

32

0

long

8Byte

64

0

float

4Byte

32

0.0f

double

8Byte

64

0.0d

boolean

-

-

false

在一些资料上都有上述介绍。对于其他类型都好理解,唯独对于boolean,长度一直没有很好的说明。我们来看看jvm中是如何实现的。

2.jvm规范描述

首先来看看jvm规范对boolean的描述:

2.3.4 The boolean Type
Although the Java Virtual Machine defines a boolean type, it only provides
very limited support for it. There are no Java Virtual Machine instructions solely
dedicated to operations on boolean values. Instead, expressions in the Java
programming language that operate on boolean values are compiled to use values
of the Java Virtual Machine int data type.
The Java Virtual Machine does directly support boolean arrays. Its newarray
instruction (§newarray) enables creation of boolean arrays. Arrays of type
boolean are accessed and modified using the byte array instructions baload and
bastore (§baload, §bastore).
In Oracle’s Java Virtual Machine implementation, boolean arrays in the Java
programming language are encoded as Java Virtual Machine byte arrays, using 8 bits per
boolean element.
The Java Virtual Machine encodes boolean array components using 1 to represent
true and 0 to represent false. Where Java programming language boolean values
are mapped by compilers to values of Java Virtual Machine type int, the compilers
must use the same encoding.

大意是说,尽管在java虚拟机中定义了boolean类型,但是对它的支持是很有限的。没有专门针对boolean的java虚拟机指令,相反,java语言中操作boolean的表达式,在编译的时候,会被转换为int类型的值。 java虚拟机直接支持boolean数组,newarray指令允许创建boolean数组,使用字节数据的指令baload和bastore访问和修改boolean类型的数组。 在oracle的java虚拟机中,java语言中的boolean数组被编码为java虚拟机中的字节数组。每个boolean元素使用8位,1个字节来表示。 java虚拟机中使用1表示真,0表示假,来对boolean进行编码。如果编译器将java语言的boolean值映射位虚拟机类型的int类型,则编译器也必须使用相同的编码。

通过上述描述可以看出,实际上,boolean的变量是被当作int类型来处理的,而boolean数组,会被特殊处理。

3.java字节码

我们写一段java代码来进行验证:

package com.dhb.test;

import java.nio.ByteBuffer;

public class BooleanTest {

	public static void main(String[] args) {
		boolean a = false;
		boolean[] array = {true,true,true,true,true};
	}
}

通过javap来查看其字节码:

$ javap -c -l -s -verbose BooleanTest.class
Classfile /D:/workspace-git/MyProject/target/classes/com/dhb/test/BooleanTest.class
  Last modified 2020-9-9; size 477 bytes
  MD5 checksum ae4d3635b02ccda5fe262ef944987b72
  Compiled from "BooleanTest.java"
public class com.dhb.test.BooleanTest
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #3.#21         // java/lang/Object."<init>":()V
   #2 = Class              #22            // com/dhb/test/BooleanTest
   #3 = Class              #23            // java/lang/Object
   #4 = Utf8               <init>
   #5 = Utf8               ()V
   #6 = Utf8               Code
   #7 = Utf8               LineNumberTable
   #8 = Utf8               LocalVariableTable
   #9 = Utf8               this
  #10 = Utf8               Lcom/dhb/test/BooleanTest;
  #11 = Utf8               main
  #12 = Utf8               ([Ljava/lang/String;)V
  #13 = Utf8               args
  #14 = Utf8               [Ljava/lang/String;
  #15 = Utf8               a
  #16 = Utf8               Z
  #17 = Utf8               array
  #18 = Utf8               [Z
  #19 = Utf8               SourceFile
  #20 = Utf8               BooleanTest.java
  #21 = NameAndType        #4:#5          // "<init>":()V
  #22 = Utf8               com/dhb/test/BooleanTest
  #23 = Utf8               java/lang/Object
{
  public com.dhb.test.BooleanTest();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 5: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/dhb/test/BooleanTest;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=4, locals=3, args_size=1
         0: iconst_0
         1: istore_1
         2: iconst_5
         3: newarray       boolean
         5: dup
         6: iconst_0
         7: iconst_1
         8: bastore
         9: dup
        10: iconst_1
        11: iconst_1
        12: bastore
        13: dup
        14: iconst_2
        15: iconst_1
        16: bastore
        17: dup
        18: iconst_3
        19: iconst_1
        20: bastore
        21: dup
        22: iconst_4
        23: iconst_1
        24: bastore
        25: astore_2
        26: return
      LineNumberTable:
        line 8: 0
        line 9: 2
        line 10: 26
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      27     0  args   [Ljava/lang/String;
            2      25     1     a   Z
           26       1     2 array   [Z
}
SourceFile: "BooleanTest.java"

可以看到,在定义变量 boolean a = false的时候:

     0: iconst_0
     1: istore_1

是将int类型的0压入栈顶。之后将int类型的值,存入第一个int类型的变量中去。我们可以对照本地变量表:

 LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      27     0  args   [Ljava/lang/String;
            2      25     1     a   Z
           26       1     2 array   [Z

slot为1的就是a。那么a=false实际上就是将a=1。 之后再来看对数组的操作:boolean[] array = {true,true,true,true,true};会转换为:

     2: iconst_5
     3: newarray       boolean
     5: dup
     6: iconst_0
     7: iconst_1
     8: bastore
     9: dup
    10: iconst_1
    11: iconst_1
    12: bastore
    13: dup
    14: iconst_2
    15: iconst_1
    16: bastore
    17: dup
    18: iconst_3
    19: iconst_1
    20: bastore
    21: dup
    22: iconst_4
    23: iconst_1
    24: bastore
    25: astore_2

首先是将int 5压入栈顶,之后用这个数字newarray 。之后将iconst_0 和iconst_1 执行bastore。意思就是将数组的第0位将int1设置。之后通过byte数组的方式 bastore到数组中。 实际上可以看出,在字节码中,boolean变量实际上与int等同。而boolean数组的操作,则与操作byte数组等价。

4.代码证明

我们可以用stackOverFlow上的一段代码进行证明,在hotSpot 1.8中,用如下代码证明:

package com.dhb.test;

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

	public static void main(String[] args) {
		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();
	}


	static 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;
	}

	static 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;
	}
}

其执行结果:

Size for LotsOfBooleans: 94654104
Average size: 94.654104
Size for LotsOfInts: 336376256
Average size: 336.376256
0

平均每个boolean数组的大小为94Bit,而boolean数组中有80个boolean,那么每个boolean的长度,不可能超过1个Byte。

5.结论

根据以上描述,可以得出结论: boolean在oracle的jvm中,至少在HotSpot 1.8中,boolean变量的长度为4 Byte。而boolean数组中,每个boolean长度为1 Byte。

由于java不同jvm的实现实际上可能会有不同,以上结论仅限于hotSpot 版本。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Visualizing the impact of ordered vs. random index insertion in InnoDB (16 顺序插入和随机插入索引的影响可视化分析)

    许多dba都知道,按照“随机”顺序(或者实际上与按键排序有很大区别的任何顺序)构建索引的效率会低得多。然而,通常很难真正理解为什么会这样。通过innodb_ru...

    冬天里的懒猫
  • java线程池(六):ForkJoinPool源码分析之二(WorkQueue源码)

    在前面介绍了ForkJoinPool的骨架源码之后,我们来看看ForkJoinPool的核心组成。WorkQueue的源码。

    冬天里的懒猫
  • 聊聊java中的哪些Map:(二)HashMap中的TreeNode

    TreeNode则是hashMap树化之后,组成树的基本节点。需要注意的是,TreeNode继承了LiknedHashMap.Entry ,LinkedHas...

    冬天里的懒猫
  • 从薪火相传的密钥文件到“密码即服务”

    当我们加入一个团队时,通常会有一个Readme文档告诉你项目代码库的下载链接。除此之外它会告诉你需要向团队“前辈”索要密钥文件,不然你的代码是不能在本地启动的。...

    极客人
  • CentOS6.9下制作Kickstart无人值守安装的自定义ISO镜像

    之前介绍过PXE+Kickstart实现无人值守自动化安装CentOS系统,现通过自定义制作ISO镜像的方式,制作出Kickstart无人值守一键安装的Cent...

    yuanfan2012
  • python3一些用法

    python3自定义算法排序 sorted(a1, key = functools.cmp_to_key(cmp)) a1是待排序list,cmp为排序函数

    py3study
  • 爬取斗图网图片,使用xpath格式来匹配内容,对请求伪装成浏览器, Referer 防跨域请求

    小小咸鱼YwY
  • 区块链媒体:实行“知识付费”机制,让内容创作者获得更多利益!

    知识付费由来已久,相继出现的知识付费平台已成为了媒体行业的一大新风口。而作为区块链技术背景下的区块链媒体其实本身就具备着知识付费奖励机制,如链讯头条、极...

    望名天
  • VueJS 开发常见问题集锦

    由于公司的前端开始转向 VueJS,最近开始使用这个框架进行开发,遇到一些问题记录下来,以备后用。

    疯狂的技术宅
  • 新冠肺炎数据里学到的四个数据分析和机器学习知识

    虽然现在大家很容易获取机器学习和数据科学的学习工具,但是除了学习如何使用工具以外,往工具里输入数据之前如何有效地探索数据,并找出其局限性也同样重要。

    统计学家

扫码关注云+社区

领取腾讯云代金券