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).因此,当我增加数组大小时,需要增加限制:
为什么看起来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
我猜你所看到的内容可以通过JVM中的堆如何组织来轻松解释.
将参数传递-Xmx给JVM时,您将定义最大堆大小应该是什么.但是,它与您可以分配的数组的最大大小没有直接关系.
在JVM中,垃圾收集器负责为对象分配内存和清理死对象.垃圾收集器决定它如何组织堆.
你通常会有一些叫做伊甸园空间的东西,然后是两个幸存者空间,最后是终身一代.所有这些都在堆内,并且GC在它们之间划分最大堆.有关这些内存池的更多详细信息,请查看以下答案:https://stackoverflow.com/a/1262474/150339
我不知道默认值是什么,它们可能确实取决于您的系统.我刚刚检查(使用sudo jmap PID)内存池如何在运行Ubuntu 64位和Oracle Java 7的系统上运行的应用程序中分配堆.该机器具有1.7GB内存.
在该配置中,我只传递-Xmx给JVM,GC按如下方式划分堆:
如果你有类似的发行版,那就意味着151MB的最大连续块是在终身代,并且大约是100MB.由于数组是连续的内存块,并且您根本无法将对象跨越多个内存池,因此它解释了您所看到的行为.
您可以尝试使用垃圾收集器参数.在这里检查垃圾收集器参数:http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
你的结果对我来说似乎很合理.
在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 (...)
这些空间并不完全等于我的计算,但它们就在附近.
| 归档时间: |
|
| 查看次数: |
451 次 |
| 最近记录: |