首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java数组似乎每个字符需要超过2个字节。

Java数组似乎每个字符需要超过2个字节。
EN

Stack Overflow用户
提问于 2013-06-27 13:40:13
回答 3查看 558关注 0票数 15

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

代码语言:javascript
复制
package com.some.package.xmlfun;
public class Main {

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

    }
}

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

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

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

同样,当我创建一个long数组时,它似乎需要每长12字节,而不是8字节,int则需要6字节而不是4字节。

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

使用- java -Xmx151M -cp . com.some.package.xmlfun.Main运行

EN

回答 3

Stack Overflow用户

发布于 2013-06-27 13:46:37

我想您所看到的可以很容易地通过JVM中的堆的组织来解释。

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

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

你通常有一个叫做伊甸园的空间,然后是两个幸存者空间,最后是终身代。所有这些都在堆中,GC将最大堆划分在其中。有关这些内存池的更多细节,请查看这个精彩的答案:https://stackoverflow.com/a/1262474/150339

我不知道默认值是什么,它们可能确实取决于您的系统。我刚刚(使用sudo jmap PID)检查了在运行Ubuntu64位和Oracle的Java 7的系统上,内存池是如何划分堆的。机器有1.7GB内存。

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

  • 大约27%的伊甸园空间
  • 每个幸存者空间约为3%
  • 约67%为终身代。

如果您有类似的发行版,这将意味着您的151 in中最大的连续块处于终身代,并且大约为100 in。因为数组是一个连续的内存块,而且您不能有一个对象跨多个内存池,所以它解释了您所看到的行为。

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

你的结果在我看来很合理。

票数 8
EN

Stack Overflow用户

发布于 2013-06-27 14:09:57

如果您查看数据的大小(例如,使用Visual ),您会发现数组的大小实际上是每个字符2字节。

这里的问题是JVM试图在堆的旧代中适应整个数组,并且这个生成的大小受到新/旧代大小的比率的限制。

使用-XX:NewRatio=5运行将纠正问题(默认值为2)。

票数 1
EN

Stack Overflow用户

发布于 2013-06-27 14:10:21

我将努力加强布鲁诺的回答。我现在试过这个代码:

代码语言:javascript
复制
public static void main(String[] args) throws IOException {
    char [] chars = new char[50 * 1024 * 1024];
    System.out.println(Runtime.getRuntime().freeMemory());
    System.out.println(Runtime.getRuntime().totalMemory());
    System.out.println(Runtime.getRuntime().maxMemory());
}

产出如下:

代码语言:javascript
复制
38156248
143654912
143654912

很明显,为了JVM的其他目的,40 MB是免费的。我最好的猜测是为了新一代的空间。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17344782

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档