无法在具有大堆大小的64位Windows 7中运行64位JVM

时间:2012-06-04 22:08:29

标签: java windows memory-management 64-bit

这是64位Windows 7 Enterprise和64位Java 7:

java version "1.7.0_04"
Java(TM) SE Runtime Environment (build 1.7.0_04-b20)
Java HotSpot(TM) 64-Bit Server VM (build 23.0-b21, mixed mode)

使用C:\Windows\SystemWOW64\cmd.exe的shell(我错误地认为是64位版本)C:\Windows\System32\cmd.exe(我刚刚发现,礼貌) Pulsar是一个64位应用程序,尽管路径名称。)

程序本身很简单:

public class Trivial
{
    public static void main(String[] args) {
        System.out.println("total = " + toMB(Runtime.getRuntime().totalMemory()));
        System.out.println("max   = " + toMB(Runtime.getRuntime().maxMemory()));
    }

    private static long toMB(long bytes) {
        return bytes / (1024L * 1024L);
    }
}

我只是在用不同的-Xmx-Xms参数搞错,看看会发生什么。虽然我在64位Windows上使用64位Java,但我可以使用我想要的最大和最小堆大小,但这不是正在发生的事情。

java -Xmx16G -Xms2G Trivial(例如)工作正常。但是,java -Xmx16G -Xms4G Trivial给了我:

Error occurred during initialization of VM
Could not reserve enough space for object heap

Weirder(对我而言),java -Xmx16G -Xms3G Trivial给出了不同的错误:

Error occurred during initialization of VM
Unable to allocate tables for parallel garbage collection for the requested heap size.
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

尝试拆分2G3G之间的差异以查看是否存在特定大小,我尝试java -Xmx16G -Xms2900M Trivial并且它有效。然后我尝试-Xms2960M并且它有效。 -Xms2970m JVM崩溃了:

#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (malloc) failed to allocate 1048576 bytes for E in C:\jdk7u2_64p\jdk7u4\hotspot\src\share\vm\utilities/taskqueue.hpp
# An error report file with more information is saved as:
# C:\Users\QuantumMechanic\Temp\hs_err_pid10780.log

一直持续到-Xms2995M,当它切换回“无法为并行垃圾收集分配表”消息并且随着-Xms进一步增加而停留在那里。

可能发生什么事?从cmd.exe(甚至是64位)启动某些内容会产生一些进程大小限制吗? Windows(或JVM)需要一个巨大的内存块吗? (但那为什么不同的消息)?还有别的吗?

2 个答案:

答案 0 :(得分:5)

SysWoW64指的是32位Windows on Windows 64。简化:32位窗口在Windows 64bit上运行。

因此,您明确要求在32位cmd shell中运行。

请参阅:

http://en.wikipedia.org/wiki/WoW64

答案 1 :(得分:4)

在64位系统中,您有2 ^ 63Bytes的用户地址空间,但您仍然只能映射您拥有的实际内存量(物理+页面文件+映射文件)。

当JVM创建堆时,它使用C malloc()来请求初始内存块,然后它将自己管理块 。即使您在堆上根本没有任何对象,也要使用该块。

由于您指定了-Xms,这是内存池的最小值,因此JVM只会尝试从操作系统中请求该内存量或因为无法满足您的命令而失败。

我想如果你想看到64位Java的优势。也许您可以尝试打开大于4GB的文件进行随机访问,并将其映射到MappedByteBuffer。