Java char数组似乎每个char需要超过2个字节

use*_*238 15 java primitive jvm sizeof char

当我运行以下程序(运行"java -Xmx151M -cp . com.some.package.xmlfun.Main")时:

package com.some.package.xmlfun;
public class Main {

    public static void main(String [] args) {
        char [] chars = new char[50 * 1024 * 1024];

    }
}
Run Code Online (Sandbox Code Playgroud)

我需要将最大内存增加到至少151M(-Xmx151M).因此,当我增加数组大小时,需要增加限制:

  • 50*1024*1024 - > -Xmx151M
  • 100*1024*1024 - > -Xmx301M
  • 150*1024*1024 - > -Xmx451M

为什么看起来java每个字符需要3个字节,而不是文档建议的2个字节?

此外,当我类似地创建长数组时,似乎每个长度需要12个字节,而不是8个,使用int它需要6个字节而不是4个.通常看起来它需要array_size*element_size*1.5

用.编译 - javac \com\som\package\xmlfun\\*java

跑步 - java -Xmx151M -cp . com.some.package.xmlfun.Main

Bru*_*eis 8

我猜你所看到的内容可以通过JVM中的堆如何组织来轻松解释.

将参数传递-Xmx给JVM时,您将定义最大堆大小应该是什么.但是,它与您可以分配的数组的最大大小没有直接关系.

在JVM中,垃圾收集器负责为对象分配内存和清理死对象.垃圾收集器决定它如何组织堆.

你通常会有一些叫做伊甸园空间的东西,然后是两个幸存者空间,最后是终身一代.所有这些都在堆内,并且GC在它们之间划分最大堆.有关这些内存池的更多详细信息,请查看以下答案:https://stackoverflow.com/a/1262474/150339

我不知道默认值是什么,它们可能确实取决于您的系统.我刚刚检查(使用sudo jmap PID)内存池如何在运行Ubuntu 64位和Oracle Java 7的系统上运行的应用程序中分配堆.该机器具有1.7GB内存.

在该配置中,我只传递-Xmx给JVM,GC按如下方式划分堆:

  • 伊甸园空间约占27%
  • 每个幸存者空间约3%
  • 终身约占67%.

如果你有类似的发行版,那就意味着151MB的最大连续块是在终身代,并且大约是100MB.由于数组是连续的内存块,并且您根本无法将对象跨越多个内存池,因此它解释了您所看到的行为.

您可以尝试使用垃圾收集器参数.在这里检查垃圾收集器参数:http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

你的结果对我来说似乎很合理.


joh*_*902 6

在Java HotSpot VM中,堆分为"新一代"和"旧一代".数组必须位于其中任何一个中.新旧一代尺寸比例的默认值为2. (实际上表示old/new=2)

因此,通过一些简单的数学计算,可以看出151MB的堆可以拥有50.33MB的新一代和100.67MB的旧代.另外一个150MB的堆正好有100MB的老一代.你的阵列+其他所有东西(例如args)将耗尽100MB,因此产生OutOfMemoryError.


我试着跑

java -Xms150m -Xmx150m -XX:+PrintGCDetails Main > c.txt
Run Code Online (Sandbox Code Playgroud)

来自 c.txt

(...)
Heap
 PSYoungGen      total 44800K, used 3072K (addresses...)
  eden space 38400K, 8% used (...)
  from space 6400K, 0% used (...)
  to   space 6400K, 0% used (...)
 ParOldGen       total 102400K, used 217K (...)
  object space 102400K, 0% used (...)
 PSPermGen       total 21248K, used 2411K (...)
  object space 21248K, 11% used (...)

这些空间并不完全等于我的计算,但它们就在附近.