day*_*mer 8 java memory bits memory-management data-structures
我希望以System.currentTimeInMillis最小的空间存储在内存中.因为我必须将数百万存储在内存中.
我转换它给binaryString了我41 bits
这是我的计划
public class BitSetSize {
public static void main(final String[] args) {
final long currentTimeMillis = System.currentTimeMillis();
final String currentTimeToBinaryString = Long.toBinaryString(currentTimeMillis);
System.out.println("Size in bits: " + currentTimeToBinaryString.length());
final BitSet bitSet = BitSet.valueOf(new long[]{currentTimeMillis});
System.out.println("Bitset length: " + bitSet.length());
System.out.println("Bitset size: " + bitSet.size());
System.out.println("Size of biset object(bytes): " + MemoryMeasurer.measureBytes(bitSet));
}
}
Run Code Online (Sandbox Code Playgroud)
但是,当我运行它时,我得到了
Size in bits: 41
Bitset length: 41
Bitset size: 64
Size of biset object(bytes): 48
Run Code Online (Sandbox Code Playgroud)
问
-为什么bitSet.length()和bitSet.size()不同?我认为length()是正确的?
- 我正在使用记忆测量器来了解bitSet它的大小,但它告诉我48 bytes,为什么不(41/8) byte呢?
我很迷惑
为什么 bitSet.length() 和 bitSet.size() 不同?我假设 length() 是正确的吗?
的BitSet.size()是,它使用存储比特值的内部数据结构的大小。由于BitSet内部使用long[]数组,因此大小始终是 64 位的倍数。例如,如果您在 a 中设置第 64 位,BitSet则BitSet必须增加long[]数组的容量才能存储该值,因为每个 long 只能“存储”64 位。例如
BitSet bitSet = new BitSet();
for (int i = 0; i <= 64; i++) {
bitSet.set(i, true);
System.out.println(bitSet.size());
}
Run Code Online (Sandbox Code Playgroud)
BitSet.length()返回 中实际占用的位BitSet。所以如果你创建一个新的BitSet它的长度是 0。如果你然后设置第 4 位长度将是 5。size将保持 64,因为只需要一个长度来存储 5 位。
BitSet bitSet = new BitSet();
System.out.println(bitSet.length()); // 0
bitSet.set(4, true);
System.out.println(bitSet.size()); // 64
System.out.println(bitSet.length()); // 5
Run Code Online (Sandbox Code Playgroud)
我正在使用 memory-measurer 来了解 bitSet 的大小,但它告诉我 48 字节,为什么不是 (41/8) 字节?
因为内存填充。也称为数据结构对齐。该BitSet对象需要内存中的数学 41 字节。
long[]long数组中的8 个字节wordsInUse int变量的4 个字节sizeIsSticky boolean 但是 jvm 无法分配 41 位,因此它将其四舍五入为 8 的下一个倍数。即 48。
此大小可能会有所不同,因为对象标头大小可能因一种 JVM 实现而异。所以如果对象头是 16 个字节。总数将为 49,jvm 将其四舍五入为 8 的下一个倍数。在本例中为 56。
首先,我想建议使用正确的工具来分析 JVM 中的对象布局方案 - JOL。在您的情况下( java -jar jol-cli/target/jol-cli.jar internals java.util.BitSet) JOL 会产生以下结果:
Running 64-bit HotSpot VM.
Using compressed references with 3-bit shift.
Objects are 8 bytes aligned.
Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
java.util.BitSet object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) f4 df 9f e0 (11110100 11011111 10011111 11100000) (-526393356)
12 4 int BitSet.wordsInUse 0
16 1 boolean BitSet.sizeIsSticky false
17 3 (alignment/padding gap) N/A
20 4 long[] BitSet.words [0]
Instance size: 24 bytes (reported by Instrumentation API)
Space losses: 3 bytes internal + 0 bytes external = 3 bytes total
Run Code Online (Sandbox Code Playgroud)
由于静态字段,您的计算不正确,因此空BitSet本身保留 24 个字节。请注意,这些计算并非 100% 准确,因为它没有考虑long[]对象的大小。所以正确的结果是java -jar jol-cli/target/jol-cli.jar externals java.util.BitSet:
Running 64-bit HotSpot VM.
Using compressed references with 3-bit shift.
Objects are 8 bytes aligned.
Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
java.util.BitSet@6b25f76bd object externals:
ADDRESS SIZE TYPE PATH VALUE
7ae321a48 24 java.util.BitSet (object)
7ae321a60 24 [J .words [0]
Run Code Online (Sandbox Code Playgroud)
这意味着空BitSet本身使用 48 个字节,包括长数组。您还可以获取不同VM模式下的估计对象布局java -jar jol-cli/target/jol-cli.jar estimates java.util.BitSet
| 归档时间: |
|
| 查看次数: |
5380 次 |
| 最近记录: |