为什么未定义 Java 的布尔基元大小?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1907318/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 23:45:06  来源:igfitidea点击:

Why is Java's boolean primitive size not defined?

javaboolean

提问by Joel

The Java Virtual Machine Specificationsays that there is limited support for boolean primitivetypes.

Java虚拟机规范说有布尔有限的支持原始类型。

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.

没有专用于布尔值运算的 Java 虚拟机指令。相反,Java 编程语言中对布尔值进行操作的表达式被编译为使用 Java 虚拟机 int 数据类型的值。

The above implies (although I may have misinterpreted it) that the int data type is used when operating on booleans, but this is a 32 bit memory construct. Given that a boolean only represents 1 bit of information:

以上暗示(尽管我可能误解了它)在对布尔值进行操作时使用 int 数据类型,但这是一个 32 位内存结构。鉴于布尔值仅表示 1 位信息:

  • Why is a byte, or short, type not used as the proxy for a boolean instead of int?
  • For any given JVM what's the most reliable way of finding out exactly how much memory is used to store a boolean type?
  • 为什么字节或短类型不用作布尔值而不是 int 的代理?
  • 对于任何给定的 JVM,找出用于存储布尔类型的内存的最可靠方法是什么?

采纳答案by kdgregory

Short answer: yes, boolean values are manipulated as 32-bit entities, but arrays of booleans use 1 byte per element.

简短回答:是的,布尔值作为 32 位实体进行操作,但布尔数组每个元素使用 1 个字节。

Longer answer: the JVM uses a 32-bit stack cell, used to hold local variables, method arguments, and expression values. Primitives that are smaller than 1 cell are padded out, primitives larger than 32 bits (long and double) take 2 cells. This technique minimizes the number of opcodes, but does have some peculiar side-effects (such as the need to mask bytes).

更长的答案:JVM 使用 32 位堆栈单元,用于保存局部变量、方法参数和表达式值。小于 1 个单元的基元被填充,大于 32 位(长和双)的基元占用 2 个单元。这种技术最大限度地减少了操作码的数量,但确实有一些特殊的副作用(例如需要屏蔽字节)。

Primitives stored in arrays may use less than 32 bits, and there are different opcodes to load and store primitive values from an array. Boolean and byte values both use the baloadand bastoreopcodes, which implies that boolean arrays take 1 byte per element.

存储在数组中的基元可能使用少于 32 位,并且有不同的操作码可以从数组加载和存储基元值。布尔值和字节值都使用baloadbastore操作码,这意味着布尔数组每个元素占用 1 个字节。

As far as in-memory object layout goes, this is covered under the "private implementation" rules, it can be 1 bit, 1 byte, or as another poster noted, aligned to a 64-bit double-word boundary. Most likely, it takes the basic word size of the underlying hardware (32 or 64 bits).

就内存对象布局而言,这包含在“私有实现”规则下,它可以是 1 位、1 字节,或者如另一张海报指出的那样,与 64 位双字边界对齐。最有可能的是,它采用底层硬件的基本字长(32 位或 64 位)。



As far as minimizing the amount of space that booleans use: it really isn't an issue for most applications. Stack frames (holding local variables and method arguments) aren't very large, and in the big scheme a discrete boolean in an object isn't that large either. If you have lots of objects with lots of booleans, then you can use bit-fields that are managed via your getters and setters. However, you'll pay a penalty in CPU time that is probably bigger than the penalty in memory.

至于最小化布尔值使用的空间量:对于大多数应用程序来说,这确实不是问题。堆栈帧(保存局部变量和方法参数)不是很大,而且在大方案中,对象中的离散布尔值也不是那么大。如果您有很多带有很多布尔值的对象,那么您可以使用通过 getter 和 setter 管理的位域。但是,您将付出的 CPU 时间代价可能大于内存代价。

回答by Thomas Jung

The boolean mapping was done with a 32bit CPU in mind. The int value has 32 bits so it can be processed in one operation.

布尔映射是在考虑到 32 位 CPU 的情况下完成的。int 值有 32 位,因此可以在一次操作中进行处理。

Here's a solution from Peter Norvig's Java IAQ: Infrequently Answered Questionsto measure the size (with some imprecision):

这是来自Peter Norvig 的 Java IAQ的解决方案测量大小的不常见问题解答(有些不精确):

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.");

回答by akuhn

A single boolean somewhere in the inheritance hierarchy can use up to 8 bytes! This is due to padding. More details can be found in How much memory is used by my Java object?:

继承层次结构中某处的单个布尔值最多可以使用 8 个字节!这是由于填充。更多细节可以在我的 Java 对象使用了多少内存中找到

Coming back to the question of how much a boolean consumes, yes it does consume at least one byte, but due to alignment rules it may consume much more. IMHO it is more interesting to know that a boolean[] will consume one byte per entry and not one bit,plus some overhead due to alignment and for the size field of the array. There are graph algorithms where large fields of bits are useful, and you need to be aware that, if you use a boolean[] you need almost exactly 8 times more memory than really needed (1 byte versus 1 bit).

回到布尔值消耗多少的问题,是的,它确实消耗了至少一个字节,但由于对齐规则,它可能消耗更多。恕我直言,更有趣的是,布尔 [] 将每个条目消耗一个字节而不是一个位,再加上由于对齐和数组的大小字段而产生的一些开销。有一些图形算法,其中大的位字段很有用,您需要注意的是,如果您使用 boolean[],您需要的内存几乎是实际需要的内存的 8 倍(1 字节对 1 位)。

回答by Hardcoded

CPUs operate on a specific datatype length. In case of 32bit CPUs they are 32 bits long and therefore what you call 'int' in Java. Everything below or above that must be filled or splitted to this length before the CPU can process it. This doesn't take much time, but if you need 2 CPU cycles instead of 1 for basic operations, this means doubled costs/time.

CPU 在特定的数据类型长度上运行。对于 32 位 CPU,它们的长度为 32 位,因此您在 Java 中称之为“int”。在 CPU 可以处理它之前,必须将其下方或上方的所有内容填充或拆分为该长度。这不会花费太多时间,但如果您需要 2 个 CPU 周期而不是 1 个进行基本操作,这意味着成本/时间翻倍。

This spec is dedicated for 32bit CPUs so that they can process booleans with their native datatype.

此规范专用于 32 位 CPU,以便它们可以使用其本机数据类型处理布尔值。

You can only have one here: speed or memory - SUN decided for speed.

您在这里只能有一个:速度或内存 - SUN 决定速度。

回答by mring

Why not make one .java file like this:

为什么不制作一个这样的 .java 文件:

Empty.java

空文件

class Empty{
}

and one class like this:

和这样的一类:

NotEmpty.java

非空文件

class NotEmpty{
   boolean b;
}

Compile them both and compare the .class files with a hex editor.

编译它们并将 .class 文件与十六进制编辑器进行比较。

回答by Matthew Flynn

The 5th Edition of Java in a Nutshell(O'Reilly) says a boolean primitive type is 1 byte. That could be wrong, based on what the examination of the heap is showing. I wonder if most JVMs have issues with allocating less than a byte for variables.

Java in a Nutshell(O'Reilly)的第 5 版说布尔基本类型是 1 个字节。根据对堆的检查所显示的内容,这可能是错误的。我想知道是否大多数 JVM 都存在为变量分配少于一个字节的问题。

回答by Krishan

Boolean represents one bit of information, but its "size" isn't something that's precisely defined, say Sun Java tutorials. Boolean literals have only two possible values those are true and false. See Java Data Typesfor details.

Sun Java 教程说,布尔值表示一位信息,但它的“大小”并不是精确定义的。布尔文字只有两个可能的值,即真和假。有关详细信息,请参阅Java 数据类型