Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot run a 64-bit JVM in 64-bit Windows 7 with a large heap size

This is 64-bit Windows 7 Enterprise and 64-bit 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)

This happens using a shell of both C:\Windows\SystemWOW64\cmd.exe (which I incorrectly thought was the 64-bit version) and with C:\Windows\System32\cmd.exe (which I have just found out, courtesy of Pulsar, is a 64-bit application despite the path name).

The program itself is trivial:

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);
    }
}

I was just fooling around with different -Xmx and -Xms arguments to see what would happen. I would have though that with 64-bit Java on 64-bit Windows I could use pretty much whatever size max and initial heap I wanted, but that's not what's happening.

java -Xmx16G -Xms2G Trivial (for example) works fine. However, java -Xmx16G -Xms4G Trivial gives me:

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

Weirder (to me), java -Xmx16G -Xms3G Trivial gives a different error:

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.

Attempting to split the difference between 2G and 3G to see if there was a specific size where this happened I tried java -Xmx16G -Xms2900M Trivial and it worked. Then I tried -Xms2960M and it worked. With -Xms2970m the JVM crashed:

#
# 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

That continued until -Xms2995M when it switched back to the "unable to allocate tables for parallel garbage collection" message and stuck with that as -Xms was increased further.

What could be going on? Does launching something from cmd.exe (even a 64-bit one) impose some process size limits? Is Windows (or the JVM) requiring a single huge memory block? (But then why the different messages)? Something else?

like image 331
QuantumMechanic Avatar asked Jun 04 '12 22:06

QuantumMechanic


2 Answers

SysWoW64 refers to the 32bit Windows on Windows 64. Simplified: 32bit windows running on windows 64bit).

So you are explicitly requesting to run in a 32bit cmd shell.

Please see:

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

like image 157
Mattias Isegran Bergander Avatar answered Sep 23 '22 02:09

Mattias Isegran Bergander


In a 64-bit system, you have 2^63Bytes of user address space, but you can still only map the amount of actual memory you have (physical + page file + mapped files).

When the JVM creates the heap, it's using C malloc() to request an initial chunk of memory and then it is going to manage the chunk by itself. Even if you don't have any object on the heap at all, to the OS the chunk is being used.

Since you specified -Xms, which is the minimum value of the memory pool, the JVM will simply try to require that amount of memory from the OS or fail as it can't satisfy your command.

I guess if you want to see the advantage of 64 bit Java. Maybe you can try opening a file larger than 4GB for random access and map it to a MappedByteBuffer.

like image 40
billc.cn Avatar answered Sep 22 '22 02:09

billc.cn