Java堆中最大对象大小

4

如果我设置了最大的Java堆大小-Xmx512m,那么单个对象的可能最大大小是多少?

假设我的应用程序只有一个类,我只创建了一个对象。

那么这个对象是否有近似的大小限制呢?

我的类看起来像下面这样:

public class BigSingleObj {
    //conf will contain thousand of String.
    private Map<String, String> conf = new HashMap<String, String>();
    public String getConf(String key) {
        return conf.get(key);
    }
}

注意

我提到了我的JVM堆大小,我希望得到一个定量的回答。


3
请查看此链接:enter link description here - user6097216
3个回答

5

这取决于您使用的JRE版本。如果您使用的是x64版本,则对象占用的空间会更多。

您可以使用JOL(Java对象布局)来计算您的对象将占用多少空间。

这将为您提供一个大致的占用空间大小。


3

如果您的堆足够大,您将能够创建的最大单个Java对象(理论上)是一个带有231-1个元素的long[]。那是16GB。理论上。

但是,对于给定的堆大小,您将能够创建的最大对象取决于平台。

  1. 实际上,最大数组长度是特定于JVM的,并且略小于231-1;请参见Java数组是否有最大大小?

  2. JVM的堆被分成两个或多个“空间”,任何给定对象必须适合单个空间1。由于这个原因以及其他各种堆相关的开销,接近整个堆大小的对象是不可能的。

各种GC空间的默认大小由内存管理器计算,我从未遇到过一个简单的公式来预测大小会是什么。

因此,如果你真的想知道可以分配的最大对象大小,那么最好的方法是通过实验测量。编写一个简单的程序,分配越来越大的数组,直到出现OOME错误。但请注意,你得到的答案将取决于你的VM版本和使用的JVM命令行选项。


假设我的应用程序只有一个类,并且我正在创建一个对象。 您的BigSingleObj类实际上根本没有分配大型对象。HashMap将从小开始,随着条目被添加到其中,它会自动增长。 此外,HashMap对象实际上由许多对象组成。其中最大的是哈希数组,但HashMap的总大小将是该数组大小的5倍或更多。然后,您需要添加由键和值占用的空间...在您的情况下,这将取决于字符串大小。 所有这些意味着,在Java中可分配的最大对象的大小不是存储在大HashMap中的条目数量的有用预测器。

正如这个答案所指出的那样,您可以使用JOL工具来确定给定Java类型的实例的大小。然而,它依赖于测量实例的大小(以各种方式),而不是预测它将是什么。在您的示例中,除非您在测量之前填充了地图,否则它会给出误导性的答案(请参见脚注2)。


1 - 使用G1GC更加复杂。它将老年代分成许多标准大小的区域,可以独立地进行收集。如果一个对象的大小超过标准区域的一半,G1GC将其分类为“巨大的”,并创建一个“巨大的区域”来容纳它。这可能会触发一个完整的收集来(实际上)在区域级别上进行碎片整理。即使如此,创建巨大区域的过程也可能失败,如果堆已经太接近满或太分散。
2 - 即使您提供了一个大的capacity参数,当前版本的HashMap也会推迟内部哈希数组的分配,直到需要它。


你有任何支持你答案的来源吗? - adranale
段落1:JLS和JVMS。段落2:有关Java垃圾回收的各种Oracle文档。段落4:HashMap的javadoc(以及源代码)。段落5:典型JVM对象表示的源代码和背景知识。 - Stephen C
这是错误的,我刚刚创建了一个包含2个数组new long[Integer.MAX_VALUE-3]的类,并且使用-Xmx50G参数可以正常运行。 - pavel_orekhov
我觉得你一定在使用G1GC;请参阅更新。但即使如此,2 x 16GB也比50GB少得多。而且这是两个对象,而不是一个。 - Stephen C

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接