如果我将 运行 我的代码,我将获得多少内存?
How much memory I'll get If I'll run my code?
如果我将 运行 这段代码,我将获得多少内存?
List<Long> list = new LinkedList<>();
for (long i = 0; i < 4_000_000_000L; i++) {
list.add(i);
}
8Gb?
此类问题可以使用 Java Object Layout 工具来回答。这是测试代码:
import org.openjdk.jol.info.GraphLayout;
import org.openjdk.jol.util.VMSupport;
import java.util.*;
public class JOLTest {
public static void main(String[] args) throws Exception {
List<Long> list = new LinkedList<>();
for (long i = 0; i < 4000L; i++) {
list.add(i);
if((i+1) % 1000 == 0) {
System.out.println("i = "+(i+1));
System.out.println(GraphLayout.parseInstance(list).toFootprint());
}
}
}
}
我没有足够的内存来检查 4_000_000_000 个条目,但没有必要,因为 LinkedList
内存分配是线性的:
i = 1000
java.util.LinkedList@41a4555ed footprint:
COUNT AVG SUM DESCRIPTION
1000 24 24000 java.lang.Long
1 32 32 java.util.LinkedList
1000 24 24000 java.util.LinkedList$Node
2001 48032 (total)
i = 2000
java.util.LinkedList@41a4555ed footprint:
COUNT AVG SUM DESCRIPTION
2000 24 48000 java.lang.Long
1 32 32 java.util.LinkedList
2000 24 48000 java.util.LinkedList$Node
4001 96032 (total)
i = 3000
java.util.LinkedList@41a4555ed footprint:
COUNT AVG SUM DESCRIPTION
3000 24 72000 java.lang.Long
1 32 32 java.util.LinkedList
3000 24 72000 java.util.LinkedList$Node
6001 144032 (total)
i = 4000
java.util.LinkedList@41a4555ed footprint:
COUNT AVG SUM DESCRIPTION
4000 24 96000 java.lang.Long
1 32 32 java.util.LinkedList
4000 24 96000 java.util.LinkedList$Node
8001 192032 (total)
所以你实际上有 (48*n+32)
字节用于列表中的 n
个元素,其中 24*n
是 Long
个实例,24*n
是内部 LinkedList$Node
实例和 32
是 LinkedList
本身。因此,您的问题的答案是 192_000_000_032 bytes
... 但是此测试是在 compressed oops 工作时针对较小的 (<32Gb) -Xmx
值执行的。对于更大的数量,数字是不同的:
$ java -Xmx32G -cp test-1.0.jar JOLTest
i = 1000
java.util.LinkedList@41a4555ed footprint:
COUNT AVG SUM DESCRIPTION
1000 24 24000 java.lang.Long
1 48 48 java.util.LinkedList
1000 40 40000 java.util.LinkedList$Node
2001 64048 (total)
i = 2000
java.util.LinkedList@41a4555ed footprint:
COUNT AVG SUM DESCRIPTION
2000 24 48000 java.lang.Long
1 48 48 java.util.LinkedList
2000 40 80000 java.util.LinkedList$Node
4001 128048 (total)
i = 3000
java.util.LinkedList@41a4555ed footprint:
COUNT AVG SUM DESCRIPTION
3000 24 72000 java.lang.Long
1 48 48 java.util.LinkedList
3000 40 120000 java.util.LinkedList$Node
6001 192048 (total)
i = 4000
java.util.LinkedList@41a4555ed footprint:
COUNT AVG SUM DESCRIPTION
4000 24 96000 java.lang.Long
1 48 48 java.util.LinkedList
4000 40 160000 java.util.LinkedList$Node
8001 256048 (total)
因此在您的情况下,它实际上是 (64*n+48)
字节,即 256_000_000_048
(大约 256Gb)。
请注意,结果是在 Oracle JDK 1.8.0_40 上获得的。不能保证不同的 JDK/JVM 会产生相同的结果。
另请注意,通常 Java 集合不能容纳超过 Integer.MAX_VALUE
个元素,因为大小存储在 int
中。查看 LinkedList
实现你可以看到(假设你有足够的内存)你不会得到异常,但是大小会悄悄溢出,因此之后可能很难使用这个集合。
如果我将 运行 这段代码,我将获得多少内存?
List<Long> list = new LinkedList<>();
for (long i = 0; i < 4_000_000_000L; i++) {
list.add(i);
}
8Gb?
此类问题可以使用 Java Object Layout 工具来回答。这是测试代码:
import org.openjdk.jol.info.GraphLayout;
import org.openjdk.jol.util.VMSupport;
import java.util.*;
public class JOLTest {
public static void main(String[] args) throws Exception {
List<Long> list = new LinkedList<>();
for (long i = 0; i < 4000L; i++) {
list.add(i);
if((i+1) % 1000 == 0) {
System.out.println("i = "+(i+1));
System.out.println(GraphLayout.parseInstance(list).toFootprint());
}
}
}
}
我没有足够的内存来检查 4_000_000_000 个条目,但没有必要,因为 LinkedList
内存分配是线性的:
i = 1000
java.util.LinkedList@41a4555ed footprint:
COUNT AVG SUM DESCRIPTION
1000 24 24000 java.lang.Long
1 32 32 java.util.LinkedList
1000 24 24000 java.util.LinkedList$Node
2001 48032 (total)
i = 2000
java.util.LinkedList@41a4555ed footprint:
COUNT AVG SUM DESCRIPTION
2000 24 48000 java.lang.Long
1 32 32 java.util.LinkedList
2000 24 48000 java.util.LinkedList$Node
4001 96032 (total)
i = 3000
java.util.LinkedList@41a4555ed footprint:
COUNT AVG SUM DESCRIPTION
3000 24 72000 java.lang.Long
1 32 32 java.util.LinkedList
3000 24 72000 java.util.LinkedList$Node
6001 144032 (total)
i = 4000
java.util.LinkedList@41a4555ed footprint:
COUNT AVG SUM DESCRIPTION
4000 24 96000 java.lang.Long
1 32 32 java.util.LinkedList
4000 24 96000 java.util.LinkedList$Node
8001 192032 (total)
所以你实际上有 (48*n+32)
字节用于列表中的 n
个元素,其中 24*n
是 Long
个实例,24*n
是内部 LinkedList$Node
实例和 32
是 LinkedList
本身。因此,您的问题的答案是 192_000_000_032 bytes
... 但是此测试是在 compressed oops 工作时针对较小的 (<32Gb) -Xmx
值执行的。对于更大的数量,数字是不同的:
$ java -Xmx32G -cp test-1.0.jar JOLTest
i = 1000
java.util.LinkedList@41a4555ed footprint:
COUNT AVG SUM DESCRIPTION
1000 24 24000 java.lang.Long
1 48 48 java.util.LinkedList
1000 40 40000 java.util.LinkedList$Node
2001 64048 (total)
i = 2000
java.util.LinkedList@41a4555ed footprint:
COUNT AVG SUM DESCRIPTION
2000 24 48000 java.lang.Long
1 48 48 java.util.LinkedList
2000 40 80000 java.util.LinkedList$Node
4001 128048 (total)
i = 3000
java.util.LinkedList@41a4555ed footprint:
COUNT AVG SUM DESCRIPTION
3000 24 72000 java.lang.Long
1 48 48 java.util.LinkedList
3000 40 120000 java.util.LinkedList$Node
6001 192048 (total)
i = 4000
java.util.LinkedList@41a4555ed footprint:
COUNT AVG SUM DESCRIPTION
4000 24 96000 java.lang.Long
1 48 48 java.util.LinkedList
4000 40 160000 java.util.LinkedList$Node
8001 256048 (total)
因此在您的情况下,它实际上是 (64*n+48)
字节,即 256_000_000_048
(大约 256Gb)。
请注意,结果是在 Oracle JDK 1.8.0_40 上获得的。不能保证不同的 JDK/JVM 会产生相同的结果。
另请注意,通常 Java 集合不能容纳超过 Integer.MAX_VALUE
个元素,因为大小存储在 int
中。查看 LinkedList
实现你可以看到(假设你有足够的内存)你不会得到异常,但是大小会悄悄溢出,因此之后可能很难使用这个集合。