Java 分配字节数组以获得40亿位

Java 分配字节数组以获得40亿位,java,Java,我正在读这本书,书名是《破解Laakman的编码采访》。在这一部分中,她(作者p.g.202)做了: 她分配了40亿比特。然而,0xFFFFFFF=2^28-1不是吗?因此,她只分配了一个2^28-1/8字节的字节数组,远未接近40亿位。它只有2^28-1位。我的问题是——她错了还是我做错了什么?我们如何分配40亿比特?我试过: byte[] bitfield = new byte[0xfffffff *2]; 尽管上述情况会导致jvm耗尽堆空间 当我们在它,什么是最好的是表达十六进制值?e、

我正在读这本书,书名是《破解Laakman的编码采访》。在这一部分中,她(作者p.g.202)做了:

她分配了40亿比特。然而,0xFFFFFFF=2^28-1不是吗?因此,她只分配了一个2^28-1/8字节的字节数组,远未接近40亿位。它只有2^28-1位。我的问题是——她错了还是我做错了什么?我们如何分配40亿比特?我试过:

byte[] bitfield = new byte[0xfffffff *2];
尽管上述情况会导致jvm耗尽堆空间


当我们在它,什么是最好的是表达十六进制值?e、 0xFFFFFF或0xFFFFFF?

我第一次小跑通过这些数字得到2147483640位——大约20亿位

[Oops--没有除以8。现在我得到了268435448位。]


[您可以在Java中分配的最大大小的对象将取决于您声明的/默认的堆大小限制和JVM设计的详细信息。例如,有些对象无法分配大于16MB的单个对象,而另一些对象可能有64MB左右的限制。]

我不清楚为什么要乘以2。最简单的方法是取(40亿/8)的十六进制表示法,其中“40亿”实际上是指0x100000000

因此,使用0x100000000/8,即0x2000000:

byte[] array = new byte[0x20000000];
如果您在启动时为JVM提供了足够的内存(例如使用-Xmx900M),那么这应该很好

示例代码:

public class Test {
    public static void main(String[] args) {
        byte[] bytes = new byte[0x20000000];
    }
}
默认情况下运行:

c:\Users\Jon\Test>java Test
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at Test.main(Test.java:3)
使用更多的空间运行:

c:\Users\Jon\Test>java -Xmx900M Test

要获得40亿位,需要500000000(5亿)字节。这是488281.25K或~487兆欧。为了在内存中分配这个,您很可能需要向上调整JVM的堆大小


这本书可能有8个Fs,或者有一个typeo。

根据发布的信息,我认为你是对的。然而(考虑到十亿是一个小规模的十亿,10ˆ9),我能想到的“分配40亿比特”的方法是:

byte[] bitfield = new byte [1000 * 1000 * 1000 / 8 * 4];
分配的数组长度为500MB(根据您的默认值,可能需要额外的-Xmx):

顺便说一句:我通常用大写字母表示基数16

另一方面,亿有点模棱两可(参见短期规模与长期规模):

作为学究,我想说40亿不完全是2^32,我建议使用不能容纳这么多位的位集,但2位集可以

BitSet[] bitSets = { new BitSet(2 * 1000 * 1000 * 1000), 
                     new BitSet(2 * 1000 * 1000 * 1000) };
如果它必须是2^32位或4 Gb(小写
b
is位),那么对于两个位集来说,这稍微有点太多了

BitSet[] bitSets = { new BitSet(1 << 28), 
                     new BitSet(1 << 28),
                     new BitSet(1 << 28),
                     new BitSet(1 << 28) };
// set a bit
long bitToSet = 

bitSets[(int) (bitToSet >>> 28)]
       .set((int) (bitToSet % (1 << 28)), value);

// test is set
long bitToTest = 

boolean test = bitSets[(int) (bitToTest >>> 28)]
                     .get((int) (bitToTest % (1 << 28)));
BitSet[]位集={新位集(1>28)]

.get((int)(bitToTest%(1整数的最大值是0X7fffffff。我相信她在声明时漏掉了数字“7”。由于策略是使用位位置指示整数值(即每个字节有8位,最多可容纳8个整数),她分配数组来容纳40亿个整数

 byte x[] = new byte[0x7fffffff/8];

这可能是个错误,因为她想表示40亿个整数。 分配给0xFFFFFF/8将保存所有40亿,因为每个字节保存8位。
4年前,我在她的勘误表中添加了这个,但她把我甩了。|

我很确定她错过了F-应该是0xFFFFFF(8Fs)=2^32~4十亿字节=320亿位=>0xFFFFFFFF/8=40亿位。其中每个位的位置代表一个从1到40亿的数字。

在表示十六进制值方面,我总是发现大写字母更清晰。你确定没有8个F吗?
0xFFFFFFFF
(8个F)可以让你达到40亿
byte[]bitfield=新字节[0xfffffff*2];
应该是正确的(取决于您对“十亿”的理解)@Hristo 0xFFFFFF获取-1。默认最大内存是内存的一部分。如果您有足够的内存,则不需要设置最大内存。@Peter:IIRC,这取决于它是使用服务器VM还是客户端VM。我当然必须在我的上网本上设置它,如图所示-但我有足够的内存来运行应用程序。我的错误;我忘记了
serLinux上的默认版本是ver
,windows上的默认版本是client
。我一直想知道这是否是对windows的偏见@彼得:我认为默认的选择不仅取决于操作系统,还取决于处理器的数量。如果Java 7也发生了变化,我也不会感到惊讶……这一页表明32位windows版本始终是客户端,在64位JVM上,默认情况下始终是服务器。对于其他32位系统,这取决于machine被认为是“服务器类”,但没有说明它是什么。
BitSet[] bitSets = { new BitSet(1 << 28), 
                     new BitSet(1 << 28),
                     new BitSet(1 << 28),
                     new BitSet(1 << 28) };
// set a bit
long bitToSet = 

bitSets[(int) (bitToSet >>> 28)]
       .set((int) (bitToSet % (1 << 28)), value);

// test is set
long bitToTest = 

boolean test = bitSets[(int) (bitToTest >>> 28)]
                     .get((int) (bitToTest % (1 << 28)));
 byte x[] = new byte[0x7fffffff/8];