Java中的静态字符串常量所需的内存空间?

gmh*_*mhk 2 java heap performance memory-leaks

JVM将分配给多少内存1)静态字符串2)静态整数

我正在研究此问题,因为我遇到了“堆内存不足”异常,我的应用程序中有8个常量文件,每个文件几乎有300个静态常量。

将所有常量声明为静态是一种好的做法,还是我可以遵循的其他任何做法?

Ste*_*n C 5

JVM将分配给多少内存1)静态字符串2)静态整数

(为简化起见,我假设我们正在谈论32位JVM。还要注意,这些数字是近似值,并且特定于JVM。)

简单的第一个-每个静态Integer变量为引用占用4字节的内存,再加上4字节+ 1个对象标头(通常为8字节的IIRC)。总计-16个字节。

(如果您在谈论静态int变量,则每个变量总共4个字节int。)

静态String变量稍微复杂一点……而且更昂贵:

  • 静态参考变量是4个字节。
  • String对象具有4 x 4字节字段+ 1 x 2字对象标头:24字节。
  • 这些字段之一指的是一个char数组,该数组具有3个字的标头,并且需要(string.length() + 3) / 4字节作为内容内容-12 + 4字节的某个倍数。
  • 如果String值为编译时间常数,则将对String进行检查,这将为字符串池哈希表条目增加一些额外的字节开销。(32个字节是一个合理的猜测。)

将所有这些加起来,就可以得出(例如)每个字符串80+字节,具体取决于字符串长度。但是几乎所有这些字节都是(内部)字符串本身的表示。由于使用,只有4个字节static

我正在研究此问题,因为我遇到了“堆内存不足”异常,我的应用程序中有8个常量文件,每个文件几乎有300个静态常量。

没关系 OOME几乎可以肯定是由于其他原因。

将所有常量声明为静态是一种好的做法,还是我可以遵循的其他任何做法?

最好将实常数声明为静态变量。

但是,源代码中的大量常量变得笨拙,由于字节码文件格式的限制,最终会遇到编译错误。此时(可能很早之前),您应该将常量从源代码中移出,移入数据库或配置文件中。

在内存使用成为严重问题之前,您很可能会遇到字节码格式所施加的限制。