32-bit JVM on 64-bit Windows crashes when starting with -Xmx1300m and lots of free memory

I am struggling with Java heap space settings. Java by default is a 32-bit client, regardless of OS version (which Oracle recommends to all users). It seems to set the maximum heap size to 256 MB by default, and that is too small for me.

I use a custom launcher to launch the application. I would like it to use more memory on computers with lots of RAM, and the default is -Xmx512m for those with less RAM. As far as I know, the only way is the -Xmx static parameter (which should be set at startup).

I have a user who has 8 GB of RAM, 64-bit Windows and 32-bit Java 7. The maximum memory visible to the JVM is 4G (as returned by the OperatingSystemMXBean request). I understand why, no problem.

For some reason, my application cannot run for this user with -Xmx1300m , although it does have 2.3G free memory. He closed some applications (with 5G free memory), and yet it did not start. The error was reported to me:

 error occured during init of vm could not reserve enough space for object heap 

What's happening? Could it be that the 32-bit JVM will be able to address the โ€œfirstโ€ 4G of memory and should have a 1300M block available in these first 4 gigabytes?

How can I solve this problem, except to ask everyone to install 64-bit Java (which is hardly acceptable)?

EDIT: In case that matters, it's a fat Swing client, not an applet.

+6
source share
5 answers

This is not a matter of memory, but a matter of address space.

On those 4 GB (2 ^ 32), theoretically addressed by a 32-bit process, it is necessary to take into account the fact that the kernel of the OS requires a part of this address space (which, obviously, the process cannot touch).

And when you use Java, the address space of the java process itself is further divided between the heap, permgen, native resources, the JVM itself, etc.

You are using a 64 bit OS. Launch the 64-bit JVM. Your bytecode (i.e., all your banks) will work anyway. There is simply no reason to use a 32-bit JVM!

+2
source

Why doesn't it work?

As already mentioned, this particular user computer most likely does not have a sufficiently large contiguous block of free memory for the JVM in the 32-bit address space. The maximum 32-bit heap space depends on the system (note that both the OS and the exact version of the JVM matter), but usually it is around 1100-1600 MB on Windows. For example, on my 64-bit Windows 7 system, these are the maximum -Xmx sizes for the specific 32-bit versions of the JVM that I installed:

  • Java 7: between 1100 and 1200 m
  • Java 6: between 1400 and 1500 m
  • Java 5: between 1500 and 1600 m

The remaining memory allocated for the process is used by the OS (or the emulator, in the case of a 32-bit process on a 64-bit host), the JVM itself, and other structures used by the JVM.

Recommended Solution: Combine the 64-bit JVM with your application

If you cannot force the client to install the 64-bit JVM, link it to your application. A 64-bit address space will have a contiguous block of memory larger than 1300 MB, even if not necessarily a large enough contiguous block of physical memory.

If your software is a standalone application, this is a piece of cake to integrate the JVM. If the launcher is an applet, you may need to check the applet for the 64-bit JVM in a known place (and, if necessary, download it) before starting the application.

Do not forget about dependencies

If your application uses 32-bit native libraries, make sure that you can also get 64-bit versions of these native libraries.

What if you cannot bind the JVM or have 32-bit native dependencies?

There really is no reason why you should not associate the JVM with your application, but you might have 32-bit native dependencies that were not ported to 64-bit, in which case it won. It doesn't matter if you build the JVM, because you are still stuck with 32 bit. In this case, you can do your launcher to perform a binary search to determine the maximum heap size by repeatedly executing java -Xmx####m -version and java -Xmx####m -version output (where #### is the java -Xmx####m -version value, of course). Once you find the maximum Xmx, you can run your program with this value. (Note: a slightly safer option is to simply try to run your program and check for a heap space error by decreasing Xmx after every failed attempt to start your program.)

You will need to use a lower Xmx if you get an error message similar to one of the following:

Java 7:

 Error occurred during initialization of VM Could not reserve enough space for object heap Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit. 

Java 6:

 Error occurred during initialization of VM Could not reserve enough space for object heap Could not create the Java virtual machine. 

Java 5:

 Error occurred during initialization of VM Could not reserve enough space for object heap Could not create the Java virtual machine. 

But if you get something like the following, you know that you either found the maximum, or you can try a larger Xmx value:

 Java(TM) SE Runtime Environment (build 1.7.0_21-b11) Java HotSpot(TM) Client VM (build 23.21-b01, mixed mode) 
+2
source

I agree with the previous answers. Just a few additional comments. Yes, 32-bit can theoretically access 4 GB, but on Windows the upper half is reserved for the operating system, and the lower half for all applications. Since Windows considers Java to be a "user" program, and not part of the OS, the best you could do is 2 GB. And in practice it is much less. 1.2GB sounds right.

However, when working in 32-bit mode, I would recommend abandoning 1024 MB. If you completely delete the heap space, you may run into a more serious problem when you run out of โ€œnative memoryโ€. And if you have never experienced this before it was a real pleasure - because instead of getting a good Java stack trace, the entire JVM immediately crashes.

And I agree with everyone that you need to bite a bullet and improve your application to support 64-bit JVM. In my case, we have a wrapper for the service, so we needed to redistribute both the JVM and the 32-bit service wrapper and the 64-bit service wrapper. Then the user could register either a 32-bit or a 64-bit version.

+1
source

Windows XP is limited to 1.2 - 1.4 GB of continuous memory. Even if you have a 64-bit JVM, 32-bit emulation works the same way as for Windows XP for compatibility, i.e. Also has the same limitations.

If you want to use more memory, run the 64-bit JVM. If you do not have 32-bit DLLs, there is a reason why this is not the case.

+1
source

The application in which I work requires as much memory as I can give it. through the trial version and the error, I found that on Windows most I can reliably assign a 32-bit JVM of about 1200 MB. It changes a little, but I never knew that it was below this. On Linux running OpenJVM, I can sometimes assign 1300 MB. There are many reasons for this limitation, but from what I read, one of the main problems that stop the JVM is acquiring a larger heap than this requirement that the heap be one continuous block of memory.

As you are on a 64-bit machine running on a 64-bit operating system, I would highly recommend just switching to a 64-bit JVM. You can then assign a substantially unlimited amount of memory. However, my experiments show that more than 10 GB of memory is a serious case of diminished performance because the JVM does not seem to use it very well, and performance suffers. I believe that Java 8 will better manage large amounts of memory.

0
source

Source: https://habr.com/ru/post/948001/


All Articles