JVM分配多少内存 1)静态字符串 2)静态整数
我正在探索这个问题,因为我得到堆内存超出内存异常, 我的应用程序中有8个常量文件,每个文件几乎接近300个静态常量。
将所有常量声明为静态或其他任何可以遵循的做法是不错的做法?
答案 0 :(得分:4)
JVM将分配多少内存1)静态字符串2)静态整数
(为了简化,我假设我们正在讨论32位JVM。还要注意这些数字是近似, JVM特定。)
首先是简单的 - 每个静态Integer
变量占用4个字节的内存用于引用加上4个字节+ 1个对象头(通常为8个字节IIRC)。总计 - 16个字节。
(如果你在谈论静态int
变量,那么每int
总共有4个字节。)
静态String
变量有点复杂......而且更昂贵:
String
对象有4 x 4字节字段+ 1 x 2字对象标题:这是24个字节。(string.length() + 3) / 4
字节 - 这是12 + 4字节的倍数。添加所有内容,每个字符串得到(比如说)80+个字节,具体取决于字符串长度。但几乎所有这些字节都是(interned)String本身的表示。只有4个字节是由于使用了static
。
我正在探索这个问题,因为我得到堆内存超出内存异常,我在我的应用程序中有8个常量文件,每个文件几乎接近300个静态常量。
那是微不足道的。 OOME几乎肯定是由于别的东西。
将所有常量声明为静态或其他任何可以遵循的做法是不错的做法?
最好将实常数声明为静态,直到某一点。
但是,源代码中的大量常量变得难以处理,并且由于字节码文件格式的限制,最终会遇到编译错误。那时(可能在此之前)你应该将常量从源代码中移出并移入数据库或配置文件中。
在内存使用成为一个重要问题之前,你很可能会遇到字节码格式强加的限制。
答案 1 :(得分:3)
2400字符串常量不会让你内存不足。每个10K,只需24MB。以更常见的100字节速率,它只有240K。
我会在其他地方寻找记忆力。
答案 2 :(得分:2)
字符串对象占用多少空间当然取决于字符串的长度。
除了字符串本身的字符外,一个字符串包含一些控制字段,但我将它们视为28字节加上另一个嵌入对象(ObjectStreamField),我不确定它有多大,但无论如何它可能是一些十几个字节。每个字符占用2个字节。我认为,你需要8个字节的句柄。如果你的字符串是,每个字符大约20个字符左右,那么每个字符串可能有多达100个字节。就像Thilo所说,2400弦可能听起来很多,但它需要数百KB。除非你在谈论嵌入在手表或某些如此高度受限的环境中的Java,否则很难想象这会成为一个重要的因素,会让你的记忆消失。
答案 3 :(得分:1)
我认为这些都是静态和 final,因为你将它们称为常量。
如果将基本类型或字符串定义为常量并且该值在编译时已知,则编译器会将代码中的常量名称替换为其值。这称为compile-time constant。对于原始类型,不需要使用堆内存。字符串是实例化的,只需要将一个副本存储在堆中。
无论如何,我不相信8 x 300字符串会导致内存不足。你的问题必须在其他地方。
答案 4 :(得分:0)
你的常量弦有多大?
字符串使用的内存大小为8 * 300 * 2 *平均长度= ~5k *平均长度。使用你所有的记忆似乎不够。
将常量声明为静态,也是最终的确实是一种好习惯。 e.g。
public static final String A_STRING = "this String is constant";
注意,它是由'final'修饰符赋予常量的引用,而不是对象本身。