Maximum Java heap size of a 32-bit JVM on a 64-bit OS
Asked Answered
R

17

119

The question is not about the maximum heap size on a 32-bit OS, given that 32-bit OSes have a maximum addressable memory size of 4GB, and that the JVM's max heap size depends on how much contiguous free memory can be reserved.

I'm more interested in knowing the maximum (both theoretical and practically achievable) heap size for a 32-bit JVM running in a 64-bit OS. Basically, I'm looking at answers similar to the figures in a related question on SO.

As to why a 32-bit JVM is used instead of a 64-bit one, the reason is not technical but rather administrative/bureaucratic - it is probably too late to install a 64-bit JVM in the production environment.

Rapprochement answered 16/9, 2009 at 18:44 Comment(0)
S
77

32-bit JVMs which expect to have a single large chunk of memory and use raw pointers cannot use more than 4 Gb (since that is the 32 bit limit which also applies to pointers). This includes Sun and - I'm pretty sure - also IBM implementations. I do not know if e.g. JRockit or others have a large memory option with their 32-bit implementations.

If you expect to be hitting this limit you should strongly consider starting a parallel track validating a 64-bit JVM for your production environment so you have that ready for when the 32-bit environment breaks down. Otherwise you will have to do that work under pressure, which is never nice.


Edit 2014-05-15: Oracle FAQ:

The maximum theoretical heap limit for the 32-bit JVM is 4G. Due to various additional constraints such as available swap, kernel address space usage, memory fragmentation, and VM overhead, in practice the limit can be much lower. On most modern 32-bit Windows systems the maximum heap size will range from 1.4G to 1.6G. On 32-bit Solaris kernels the address space is limited to 2G. On 64-bit operating systems running the 32-bit VM, the max heap size can be higher, approaching 4G on many Solaris systems.

(http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#gc_heap_32bit)

Sinner answered 16/9, 2009 at 19:7 Comment(18)
No work pressure here. I know that a 64-bit JVM should have been installed in the first place. But it got me thinking about how a 32-bit JVM would work in an environment with more resources at its disposal.Rapprochement
Isn't it around 2GB becuase of the signednes? Or is that just the Sun JVM?Stretcher
Pointers are not signed - it doesn't make sense to speak of negative memory locations.Wintergreen
No, it is not 2GB because of signedness. However, part of the 4GB address space is reserved for the OS kernel. On normal consumer versions of Windows, the limit is 2GB. On Linux and server versions of Windows (32-bit) the limit is 3GB per process.Wend
@Jesper, additionally this is platform dependent. It is the PC-architecture imposing this limit.Wintergreen
@Wend I was wondering if a 32-bit JVM running on a 64-bit operating system could have a full 4 GB address space available?Wintergreen
Would it be possible for a JVM to use a 32-bit object type, but specify that those 32 bits hold a value which is 1/8 of the "real" address, so that loading a word from offset 28 of a reference held in EBX would be mov eax,[ebx*8+28]? For projects that needed between 4GB and ~32GB of heap, that would seem more efficient than using bulky 64-bit references.Mauldin
@Mauldin have a look at blogs.oracle.com/jrockit/entry/understanding_compressed_referWintergreen
@ThorbjørnRavnAndersen: Cool. I've for a long time thought Intel's 8086 addressing scheme was unfairly maligned. A mode where segment registers were simply shifted 4 places and added to an offset would be great for an object-oriented framework; it could be made even better if the upper part of the segment register was used to select among configurable addressing areas with different scale factors. Have one part of memory for small objects, with a scale factor of 8, and another for medium objects with a scale factor of 64, and one for big objects with a scale factor of 256.Mauldin
@Mauldin you need to take garbage collection into consideration. What you suggest essentially mean that you introduce several new separate memory areas where objects cannot easily migrate from one to another, making garbage collection much more complex.Wintergreen
@ThorbjørnRavnAndersen: There would be separate areas heap optimized for different sizes of objects, but I wouldn't see any obstacle to objects moving among them. One would have more space in large-grained areas than small-grained ones, so one would prefer to put objects that wouldn't benefit from smaller-grained areas into larger-grained ones when practical; further, the loss of an average of e.g. 128 bytes per allocation in the large grained area would mean one should prefer to avoid using it for objects where that loss would be significant, but...Mauldin
...shouldn't have any objection to using it for objects that are e.g. 4K or larger in size.Mauldin
@Mauldin I would suggest you look into the various research papers about garbage collection where I am certain your suggestion has been thought of and analyzed. My guess is that the janitor work needed makes it less interesting than other approaches.Wintergreen
I found most of Windows 7 installed 32bit jre in my company can not use 1.4G memory. So just do not rely on what Oracle said if you want to use as much memory as possible.Uniocular
@Uniocular you need enough RAM to support giving the JVM the additional memory (i.e. enough swap).Wintergreen
@ThorbjørnRavnAndersen In my 64bit windows7 with 64bit jre. I can set -Xmx600G, but I have only 16GB RAM installed on my PC.Uniocular
@Uniocular try to add -XX:+AlwaysPreTouch, what you are requesting is virtual space, as soon as you enable that key - it will fail.Nadanadab
kernel address space usage seems to have the biggest impactNadanadab
C
96

You can ask the Java Runtime:

public class MaxMemory {
    public static void main(String[] args) {
        Runtime rt = Runtime.getRuntime();
        long totalMem = rt.totalMemory();
        long maxMem = rt.maxMemory();
        long freeMem = rt.freeMemory();
        double megs = 1048576.0;

        System.out.println ("Total Memory: " + totalMem + " (" + (totalMem/megs) + " MiB)");
        System.out.println ("Max Memory:   " + maxMem + " (" + (maxMem/megs) + " MiB)");
        System.out.println ("Free Memory:  " + freeMem + " (" + (freeMem/megs) + " MiB)");
    }
}

This will report the "Max Memory" based upon default heap allocation. So you still would need to play with -Xmx (on HotSpot). I found that running on Windows 7 Enterprise 64-bit, my 32-bit HotSpot JVM can allocate up to 1577MiB:

[C:scratch]> java -Xmx1600M MaxMemory
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
[C:scratch]> java -Xmx1590M MaxMemory
Total Memory: 2031616 (1.9375 MiB)
Max Memory:   1654456320 (1577.8125 MiB)
Free Memory:  1840872 (1.75559234619 MiB)
[C:scratch]>

Whereas with a 64-bit JVM on the same OS, of course it's much higher (about 3TiB)

[C:scratch]> java -Xmx3560G MaxMemory
Error occurred during initialization of VM
Could not reserve enough space for object heap
[C:scratch]> java -Xmx3550G MaxMemory
Total Memory: 94240768 (89.875 MiB)
Max Memory:   3388252028928 (3184151.84297 MiB)
Free Memory:  93747752 (89.4048233032 MiB)
[C:scratch]>

As others have already mentioned, it depends on the OS.

For a 64-bit host OS, if the JVM is 32-bit, it'll still depend, most likely like above as demonstrated.

-- UPDATE 20110905: I just wanted to point out some other observations / details:

  • The hardware that I ran this on was 64-bit with 6GB of actual RAM installed. The operating system was Windows 7 Enterprise, 64-bit
  • The actual amount of Runtime.MaxMemory that can be allocated also depends on the operating system's working set. I once ran this while I also had VirtualBox running and found I could not successfully start the HotSpot JVM with -Xmx1590M and had to go smaller. This also implies that you may get more than 1590M depending upon your working set size at the time (though I still maintain it'll be under 2GiB for 32-bit because of Windows' design)
Chloromycetin answered 11/8, 2011 at 0:44 Comment(12)
I like that you actually tested rather than made guesses.Revoke
Hard to believe that a 32-bit hotspot JVM says it has 15GB free. I don't believe it. It makes no sense.Matrona
@Matrona is right. The program should be dividing by 1,048,576 (1024*1024, or 2^20), not 104,856. But, that's just a display thing. As you can see from the command, he only tried to set the maximum heap size to 1,590 MiB.Revoke
Oops, yeah, transcription error from my calculator: 1024*1024 = 1048576. Sorry I missed the 7 :) I'll edit above and re-run...Chloromycetin
Very cool answer (I would like to say the answer), with a code example, and details covering all OSes.Bonni
Following up to my previous comment: The jdocs (for windows atleast) specify that the -Xmx and -Xms paramters must be given a value that is a multiple of 1024... I'm not sure if 1590 is, so I think strange results should be expected.Bonni
Well spotted TGP1994. I think that, because I've specified 'M' and 'G' multiples, then the size (in bytes) will work out to be a multiple of 1024 bytes anyway. e.g. 1590M will be parsed to 1590*(1024*1024) = 1667235840 bytes (1628160KiB -- an even multiple of 1024 of course).Chloromycetin
For me it seems to massively fluctuate, presumably depending on the exact memory partitioning of running apps (i.e., the working set). I have situations with 4.5GB RAM free (on Win 10 x64) and yet I can only allocate 1012MB or 1024MB heap space. Is there no more detailed information/explanation of this from Oracle or similar?Perish
In my blog from 2007 (9 years ago!) I added an update, with some very good info from this SO question and this excellent blog article by Dhamvir Singh. Recommend you read his post for more detail.Chloromycetin
You should be able to do 2^64 bits of allocation even if RAM is exceeded in JVM x 64.Hemorrhoid
@AndrewScottEvans well, not really, no. Most 64-bit OSes don't allow 18 exabyte (16 exbibyte) allocations even in virtual memory, even if they had the swap to support that. It's impractical from an OS design point -- even supercomputers are limited to hundreds of gigabytes of RAM and tens, perhaps hundreds of petabytes of online storage! The address space is better used for other purposes. Anyway the program in my answer demonstrates the difference between theory and practice....Chloromycetin
I am using Oracle Java version 1.8.0_231 Windows 10 and am getting between 1400 and 1590 MB. It seems to always work with 1400 but not consistently at 1500 MB and above. Note: I have 16GB RAM, of which only 46% is used.Gemmulation
S
77

32-bit JVMs which expect to have a single large chunk of memory and use raw pointers cannot use more than 4 Gb (since that is the 32 bit limit which also applies to pointers). This includes Sun and - I'm pretty sure - also IBM implementations. I do not know if e.g. JRockit or others have a large memory option with their 32-bit implementations.

If you expect to be hitting this limit you should strongly consider starting a parallel track validating a 64-bit JVM for your production environment so you have that ready for when the 32-bit environment breaks down. Otherwise you will have to do that work under pressure, which is never nice.


Edit 2014-05-15: Oracle FAQ:

The maximum theoretical heap limit for the 32-bit JVM is 4G. Due to various additional constraints such as available swap, kernel address space usage, memory fragmentation, and VM overhead, in practice the limit can be much lower. On most modern 32-bit Windows systems the maximum heap size will range from 1.4G to 1.6G. On 32-bit Solaris kernels the address space is limited to 2G. On 64-bit operating systems running the 32-bit VM, the max heap size can be higher, approaching 4G on many Solaris systems.

(http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#gc_heap_32bit)

Sinner answered 16/9, 2009 at 19:7 Comment(18)
No work pressure here. I know that a 64-bit JVM should have been installed in the first place. But it got me thinking about how a 32-bit JVM would work in an environment with more resources at its disposal.Rapprochement
Isn't it around 2GB becuase of the signednes? Or is that just the Sun JVM?Stretcher
Pointers are not signed - it doesn't make sense to speak of negative memory locations.Wintergreen
No, it is not 2GB because of signedness. However, part of the 4GB address space is reserved for the OS kernel. On normal consumer versions of Windows, the limit is 2GB. On Linux and server versions of Windows (32-bit) the limit is 3GB per process.Wend
@Jesper, additionally this is platform dependent. It is the PC-architecture imposing this limit.Wintergreen
@Wend I was wondering if a 32-bit JVM running on a 64-bit operating system could have a full 4 GB address space available?Wintergreen
Would it be possible for a JVM to use a 32-bit object type, but specify that those 32 bits hold a value which is 1/8 of the "real" address, so that loading a word from offset 28 of a reference held in EBX would be mov eax,[ebx*8+28]? For projects that needed between 4GB and ~32GB of heap, that would seem more efficient than using bulky 64-bit references.Mauldin
@Mauldin have a look at blogs.oracle.com/jrockit/entry/understanding_compressed_referWintergreen
@ThorbjørnRavnAndersen: Cool. I've for a long time thought Intel's 8086 addressing scheme was unfairly maligned. A mode where segment registers were simply shifted 4 places and added to an offset would be great for an object-oriented framework; it could be made even better if the upper part of the segment register was used to select among configurable addressing areas with different scale factors. Have one part of memory for small objects, with a scale factor of 8, and another for medium objects with a scale factor of 64, and one for big objects with a scale factor of 256.Mauldin
@Mauldin you need to take garbage collection into consideration. What you suggest essentially mean that you introduce several new separate memory areas where objects cannot easily migrate from one to another, making garbage collection much more complex.Wintergreen
@ThorbjørnRavnAndersen: There would be separate areas heap optimized for different sizes of objects, but I wouldn't see any obstacle to objects moving among them. One would have more space in large-grained areas than small-grained ones, so one would prefer to put objects that wouldn't benefit from smaller-grained areas into larger-grained ones when practical; further, the loss of an average of e.g. 128 bytes per allocation in the large grained area would mean one should prefer to avoid using it for objects where that loss would be significant, but...Mauldin
...shouldn't have any objection to using it for objects that are e.g. 4K or larger in size.Mauldin
@Mauldin I would suggest you look into the various research papers about garbage collection where I am certain your suggestion has been thought of and analyzed. My guess is that the janitor work needed makes it less interesting than other approaches.Wintergreen
I found most of Windows 7 installed 32bit jre in my company can not use 1.4G memory. So just do not rely on what Oracle said if you want to use as much memory as possible.Uniocular
@Uniocular you need enough RAM to support giving the JVM the additional memory (i.e. enough swap).Wintergreen
@ThorbjørnRavnAndersen In my 64bit windows7 with 64bit jre. I can set -Xmx600G, but I have only 16GB RAM installed on my PC.Uniocular
@Uniocular try to add -XX:+AlwaysPreTouch, what you are requesting is virtual space, as soon as you enable that key - it will fail.Nadanadab
kernel address space usage seems to have the biggest impactNadanadab
Z
17

You don't specify which OS.

Under Windows (for my application - a long running risk management application) we observed that we could go no further than 1280MB on Windows 32bit. I doubt that running a 32bit JVM under 64bit would make any difference.

We ported the app to Linux and we are running a 32bit JVM on 64bit hardware and have had a 2.2GB VM running pretty easily.

The biggest problem you may have is GC depending on what you are using memory for.

Zip answered 16/9, 2009 at 19:3 Comment(6)
I would prefer to know the limitation for Solaris 10, but then that is only for my problem at hand. Would like to know for other OSes as well, for a rainy day :)Rapprochement
Not sure about Solaris. I would expect the VM size to be pretty big, my experience of Java on Solaris was from a few years ago. And being a Sun VM on a Sun OS on Sun hardware - things worked pretty well. I was also led to believe that there were fewer GC issues under Solaris than Linux/Windows.Zip
Which Windows was this. I believe the server versions of Windows 32-bit can handle large amounts of memory much better.Wintergreen
Ah, finally a mention of the OS ;-) You have a 64-bit kernel installed?Wintergreen
It was Win2k server. A move to Win2k3 (things move slowly..) was too late and we switched to Linux instead.Zip
Upvoted for your mention of the GC issue - very important for larger VM sizes.Stylobate
M
15

From 4.1.2 Heap Sizing:

"For a 32-bit process model, the maximum virtual address size of the process is typically 4 GB, though some operating systems limit this to 2 GB or 3 GB. The maximum heap size is typically -Xmx3800m (1600m) for 2 GB limits), though the actual limitation is application dependent. For 64-bit process models, the maximum is essentially unlimited."

Found a pretty good answer here: Java maximum memory on Windows XP.

Matrona answered 1/12, 2009 at 22:20 Comment(0)
I
14

We recently had some experience with this. We have ported from Solaris (x86-64 Version 5.10) to Linux (RedHat x86-64) recently and have realized that we have less memory available for a 32 bit JVM process on Linux than Solaris.

For Solaris this almost comes around to 4GB (http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#gc_heap_32bit).

We ran our app with -Xms2560m -Xmx2560m -XX:MaxPermSize=512m -XX:PermSize=512m with no issues on Solaris for past couple of years. Tried to move it to linux and we had issues with random out of memory errors on start up. We could only get it to consistently start up on -Xms2300 -Xmx2300. Then we were advised of this by support.

A 32 bit process on Linux has a maximum addressable address space of 3gb (3072mb) whereas on Solaris it is the full 4gb (4096mb).

Izanagi answered 4/7, 2011 at 4:55 Comment(1)
The reason for the answer given by support lies in how much addressable memory is available to a process. This depends on the Linux kernel and even on the hardware. Theoretically, the addressable memory is limited to 2^32 = 4G (and the Java heap size would be lesser than this). But, this can (theoretically) be extended using hugemem and PAE; I've not attempted this.Rapprochement
P
9

The limitations of a 32-bit JVM on a 64-bit OS will be exactly the same as the limitations of a 32-bit JVM on a 32-bit OS. After all, the 32-bit JVM will be running In a 32-bit virtual machine (in the virtualization sense) so it won't know that it's running on a 64-bit OS/machine.

The one advantage to running a 32-bit JVM on a 64-bit OS versus a 32-bit OS is that you can have more physical memory, and therefore will encounter swapping/paging less frequently. This advantage is only really fully realized when you have multiple processes, however.

Pageantry answered 16/9, 2009 at 19:2 Comment(8)
There may be a slight difference depending on the hardware and how it is virtualized. Some of the 4GB addressable space is generally used for memory mapped devices. The virtualization layer may or may not have the same memory footprint as the physical devices on the machine.Nordrheinwestfalen
Not quite. There is more room for the JVM in a 64-bit machine since the 32-bit address space does not have to be shared with the operating system or hardware interfaces.Wintergreen
That's true, but all that means is that your 32-bit-virtual-machine might have slightly different overhead than a 32-bit-actual-machine (either worse, or better). Either way, you're running the JVM on a 32-bit-machine (real or virtual) and so you'll be subject to the standard 32-bit constraints. ie: an absolute ceiling of 4GB.Pageantry
Thorbjørn: the operating system and hardware interfaces still need to be mapped into the 32-bit VM. The precise amount of overheard may be different, but it'll still be there. If you can virtualize it out under an 64-bit OS what's to stop you from virtualizing it out under a 32-bit OS? This is virtual memory we're talking about.Pageantry
LG: I disagree with your original answer. The OS kernel and any HW and bus address space it maps will chew up lots of the address space, and while this isn't mapped into the user program, it does reduce the amount "left over" after the OS has set itself up. This is a considerable amount of a 4GB 32-bit space. Traditionally, this has meant that roughly 25%-75% of the 4GB is unavailable to user processes. :-) kernel hackerFrankly
@DR, Eric, Thorbjørn +1. That's precisely why a 32-bit OS cannot use all of the 4GB RAM available.Rapprochement
LG: regarding your comment. Certainly it is theoretically possible for the OS kernel and the user process to be in separate virtual spaces, and this has been true since the original i386. However, this is not how OS kernels are written, because it makes it so hard to move data back and forth from the kernel. It's interesting that some 16-bit systems, under severe address space pressure, actually could do this. I'm sure there are some obscure 32-bit ones, too, but AFAIK it's exceedingly rare.Frankly
Laurence Gonsalves, I encourage you to look up how much memory can be made directly available to a 32-bit process under a modern 64-bit operating system.Wintergreen
E
6

As to why a 32-bit JVM is used instead of a 64-bit one, the reason is not technical but rather administrative/bureaucratic ...

When I was working for BEA, we found that the average application actually ran slower in a 64-bit JVM, then it did when running in a 32-bit JVM. In some cases, the performance hit was as high as 25% slower. So, unless your application really needs all that extra memory, you were better off setting up more 32-bit servers.

As I recall, the three most common technical justifications for using a 64-bit that BEA professional services personnel ran into were:

  1. The application was manipulating multiple massive images,
  2. The application was doing massive number crunching,
  3. The application had a memory leak, the customer was the prime on a government contract, and they didn't want to take the time and the expense of tracking down the memory leak. (Using a massive memory heap would increase the MTBF and the prime would still get paid)

.

Eddings answered 15/3, 2013 at 19:13 Comment(1)
That is nice you provide first hand advice, BEA's ex-worker :)Payday
S
4

The JROCKIT JVM currently owned by Oracle supports non-contiguous heap usage, thus allowing the 32 bit JVM to access more then 3.8 GB of memory when the JVM is running on a 64 bit windows OS. (2.8 GB when running on a 32 bit OS).

http://blogs.oracle.com/jrockit/entry/how_to_get_almost_3_gb_heap_on_windows

The JVM can be freely downloaded (registration required) at

http://www.oracle.com/technetwork/middleware/jrockit/downloads/index.html

Sestos answered 11/12, 2011 at 10:23 Comment(0)
S
4

Here is some testing under Solaris and Linux 64-bit

Solaris 10 - SPARC - T5220 machine with 32 GB RAM (and about 9 GB free)

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3750m MaxMemory
Error occurred during initialization of VM
Could not reserve space for ObjectStartArray
$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3700m MaxMemory
Total Memory: 518520832 (494.5 MiB)
Max Memory:   3451912192 (3292.0 MiB)
Free Memory:  515815488 (491.91998291015625 MiB)
Current PID is: 28274
Waiting for user to press Enter to finish ...

$ java -version
java version "1.6.0_30"
Java(TM) SE Runtime Environment (build 1.6.0_30-b12)
Java HotSpot(TM) Server VM (build 20.5-b03, mixed mode)

$ which java
/usr/bin/java
$ file /usr/bin/java
/usr/bin/java: ELF 32-bit MSB executable SPARC Version 1, dynamically linked, not stripped, no debugging information available

$ prstat -p 28274
   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/NLWP
28274 user1     670M   32M sleep   59    0   0:00:00 0.0% java/35

BTW: Apparently Java does not allocate much actual memory with the startup. It seemed to take only about 100 MB per instance started (I started 10)

Solaris 10 - x86 - VMWare VM with 8 GB RAM (about 3 GB free*)

The 3 GB free RAM is not really true. There is a large chunk of RAM that ZFS caches use, but I don't have root access to check how much exactly

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3650m MaxMemory
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3600m MaxMemory
Total Memory: 516423680 (492.5 MiB)
Max Memory:   3355443200 (3200.0 MiB)
Free Memory:  513718336 (489.91998291015625 MiB)
Current PID is: 26841
Waiting for user to press Enter to finish ...

$ java -version
java version "1.6.0_41"
Java(TM) SE Runtime Environment (build 1.6.0_41-b02)
Java HotSpot(TM) Server VM (build 20.14-b01, mixed mode)

$ which java
/usr/bin/java

$ file /usr/bin/java
/usr/bin/java:  ELF 32-bit LSB executable 80386 Version 1 [FPU], dynamically linked, not stripped, no debugging information available

$ prstat -p 26841
   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/NLWP
26841 user1     665M   22M sleep   59    0   0:00:00 0.0% java/12

RedHat 5.5 - x86 - VMWare VM with 4 GB RAM (about 3.8 GB used - 200 MB in buffers and 3.1 GB in caches, so about 3 GB free)

$ alias java='$HOME/jre/jre1.6.0_34/bin/java'

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3500m MaxMemory
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3450m MaxMemory
Total Memory: 514523136 (490.6875 MiB)
Max Memory:   3215654912 (3066.6875 MiB)
Free Memory:  511838768 (488.1274871826172 MiB)
Current PID is: 21879
Waiting for user to press Enter to finish ...

$ java -version
java version "1.6.0_34"
Java(TM) SE Runtime Environment (build 1.6.0_34-b04)
Java HotSpot(TM) Server VM (build 20.9-b04, mixed mode)

$ file $HOME/jre/jre1.6.0_34/bin/java
/home/user1/jre/jre1.6.0_34/bin/java: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), for GNU/Linux 2.2.5, not stripped

$ cat /proc/21879/status | grep ^Vm
VmPeak:  3882796 kB
VmSize:  3882796 kB
VmLck:         0 kB
VmHWM:     12520 kB
VmRSS:     12520 kB
VmData:  3867424 kB
VmStk:        88 kB
VmExe:        40 kB
VmLib:     14804 kB
VmPTE:        96 kB

Same machine using JRE 7

$ alias java='$HOME/jre/jre1.7.0_21/bin/java'

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3500m MaxMemory
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 -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3450m MaxMemory
Total Memory: 514523136 (490.6875 MiB)
Max Memory:   3215654912 (3066.6875 MiB)
Free Memory:  511838672 (488.1273956298828 MiB)
Current PID is: 23026
Waiting for user to press Enter to finish ...

$ java -version
java version "1.7.0_21"
Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
Java HotSpot(TM) Server VM (build 23.21-b01, mixed mode)

$ file $HOME/jre/jre1.7.0_21/bin/java
/home/user1/jre/jre1.7.0_21/bin/java: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped

$ cat /proc/23026/status | grep ^Vm
VmPeak:  4040288 kB
VmSize:  4040288 kB
VmLck:         0 kB
VmHWM:     13468 kB
VmRSS:     13468 kB
VmData:  4024800 kB
VmStk:        88 kB
VmExe:         4 kB
VmLib:     10044 kB
VmPTE:       112 kB
Squama answered 3/5, 2013 at 19:3 Comment(1)
There's some useful test results in here for the platforms we've been missing. Good work with the use of file and memory dumps too.Chloromycetin
F
3

Should be a lot better

For a 32-bit JVM running on a 64-bit host, I imagine what's left over for the heap will be whatever unfragmented virtual space is available after the JVM, it's own DLL's, and any OS 32-bit compatibility stuff has been loaded. As a wild guess I would think 3GB should be possible, but how much better that is depends on how well you are doing in 32-bit-host-land.

Also, even if you could make a giant 3GB heap, you might not want to, as this will cause GC pauses to become potentially troublesome. Some people just run more JVM's to use the extra memory rather than one giant one. I imagine they are tuning the JVM's right now to work better with giant heaps.

It's a little hard to know exactly how much better you can do. I guess your 32-bit situation can be easily determined by experiment. It's certainly hard to predict abstractly, as a lot of things factor into it, particularly because the virtual space available on 32-bit hosts is rather constrained.. The heap does need to exist in contiguous virtual memory, so fragmentation of the address space for dll's and internal use of the address space by the OS kernel will determine the range of possible allocations.

The OS will be using some of the address space for mapping HW devices and it's own dynamic allocations. While this memory is not mapped into the java process address space, the OS kernel can't access it and your address space at the same time, so it will limit the size of any program's virtual space.

Loading DLL's depends on the implementation and the release of the JVM. Loading the OS kernel depends on a huge number of things, the release, the HW, how many things it has mapped so far since the last reboot, who knows...

In summary

I bet you get 1-2 GB in 32-bit-land, and about 3 in 64-bit, so an overall improvement of about 2x.

Frankly answered 16/9, 2009 at 19:10 Comment(9)
Unfortunately, I do not have a 64-bit environment at my disposal where I could experiment with the Xmx flag. The one that I know of has a humongous (32 * n)GB amount of RAM available, but out of bounds. That is why I wanted to know how a 32-bit JVM would work without all the constraints it normally faces in a 32-bit world.Rapprochement
Well, good question. I'm sure the basic answer is "it will work better".Frankly
Ok, I've edited my answer to focus a bit more on your actual question. :-)Frankly
≅ 3GB in 64-bit sounds just about right. Thorbjørn had already indicated why it theoretically cannot exceed 4GB. Too bad I cannot accept two answers.Rapprochement
If you have a big box, you can experiment with a 64-bit Solaris in e.g. virtualbox (which has the best Solaris guest support).Wintergreen
64-bit supports way more than 3G. 1000G is no problem. Upvoting is definitely the wrong this to do in response to this GUESS https://mcmap.net/q/49219/-max-memory-for-64bit-javaAsiaasian
@Ajax: read the question he said it's a 32-bit Java for political reasons. So he is limited to 4 GB for the sum total of Java + libraries + interpreter + all other sources of overhead. My point is that the limit he will hit will be somewhat different if he is on a 64-bit kernel vs a 32-bit kernel.Frankly
You said yourself your answer was a wild guess. Last I checked, guessing instead of testing is always a bad idea. Running a 32 bit jvm on a 64 bit windows machine WON'T help much, because you need the OS to allocate contiguous memory, and the DLLs loaded by the system limit you to 1.5-1.8G regardless of arch. If you have a 64 bit system with lots of memory, the jvm might be able to find lots of unused contiguous memory, but you won't magically get 2X benefits because the OS is 64 bits. #171705Asiaasian
If you test your assumption and link to proof, I would more than gladly apologize. Until then though, the burden of proof is on the person making the claim.Asiaasian
H
2

On Solaris the limit has been about 3.5 GB since Solaris 2.5. (about 10 years ago)

Homograph answered 2/12, 2009 at 6:51 Comment(2)
I am going to experiment with that, using Oracle Solaris Express 11.Matrona
@Peter Lawrey Uhm.. Solaris 2.5 was nearly 20 years ago if you consider the release date of May 1996.... of course it didn't EOL till around 2005.Curtilage
T
1

I was having the same problems with the JVM that App Inventor for Android Blocks Editor uses. It sets the heap at 925m max. This is not enough but I couldn't set it more than about 1200m, depending on various random factors on my machine.

I downloaded Nightly, the beta 64-bit browser from Firefox, and also JAVA 7 64 bit version.

I haven't yet found my new heap limit, but I just opened a JVM with a heap size of 5900m. No problem!

I am running Win 7 64 bit Ultimate on a machine with 24gb RAM.

Tithe answered 6/9, 2012 at 16:43 Comment(0)
D
0

I have tried setting the heap size upto 2200M on 32bit Linux machine and JVM worked fine. The JVM didnt start when I set it to 2300M.

Doubly answered 10/10, 2009 at 1:12 Comment(2)
I thought I would add that on Windows VISTA 64 bit, a 32 bit JVM maxes out at 1582m (-Xmx value). It will complain if I specify 1583m. I do not know if this value changes from machine to machine. The computer on which I tested this actually had 4 GB physical RAM.Yarndyed
@SantoshTiwari it changes from machine to machine, but here is whyNadanadab
I
0

one more point here for hotspot 32-bit JVM:- the native heap capacity = 4 Gig – Java Heap - PermGen;

It can get especially tricky for 32-bit JVM since the Java Heap and native Heap are in a race. The bigger your Java Heap, the smaller the native Heap. Attempting to setup a large Heap for a 32-bit VM e.g .2.5 GB+ increases risk of native OutOfMemoryError depending of your application(s) footprint, number of Threads etc.

Imbricate answered 5/2, 2015 at 18:50 Comment(0)
L
0

Theoretical 4gb, but in practice (for IBM JVM):

Win 2k8 64, IBM Websphere Application Server 8.5.5 32bit

C:\IBM\WebSphere\AppServer\bin>managesdk.bat -listAvailable -verbose CWSDK1003I: Доступные SDK: CWSDK1005I: Имя SDK: 1.6_32 - com.ibm.websphere.sdk.version.1.6_32=1.6 - com.ibm.websphere.sdk.bits.1.6_32=32 - com.ibm.websphere.sdk.location.1.6_32=${WAS_INSTALL_ROOT}/java - com.ibm.websphere.sdk.platform.1.6_32=windows - com.ibm.websphere.sdk.architecture.1.6_32=x86_32 - com.ibm.websphere.sdk.nativeLibPath.1.6_32=${WAS_INSTALL_ROOT}/lib/native/win /x86_32/ CWSDK1001I: Задача managesdk выполнена успешно. C:\IBM\WebSphere\AppServer\java\bin>java -Xmx2036 MaxMemory JVMJ9GC017E -Xmx слишком мала, должна быть не меньше 1 M байт JVMJ9VM015W Ошибка инициализации для библиотеки j9gc26(2): Не удалось инициализи ровать Could not create the Java virtual machine. C:\IBM\WebSphere\AppServer\java\bin>java -Xmx2047M MaxMemory Total Memory: 4194304 (4.0 MiB) Max Memory: 2146435072 (2047.0 MiB) Free Memory: 3064536 (2.9225692749023438 MiB) C:\IBM\WebSphere\AppServer\java\bin>java -Xmx2048M MaxMemory JVMJ9VM015W Ошибка инициализации для библиотеки j9gc26(2): Не удалось создать эк земпляр кучи; запрошено 2G Could not create the Java virtual machine.

RHEL 6.4 64, IBM Websphere Application Server 8.5.5 32bit

[bin]./java -Xmx3791M MaxMemory Total Memory: 4194304 (4.0 MiB) Max Memory: 3975151616 (3791.0 MiB) Free Memory: 3232992 (3.083221435546875 MiB) [root@nagios1p bin]# ./java -Xmx3793M MaxMemory Total Memory: 4194304 (4.0 MiB) Max Memory: 3977248768 (3793.0 MiB) Free Memory: 3232992 (3.083221435546875 MiB) [bin]# /opt/IBM/WebSphere/AppServer/bin/managesdk.sh -listAvailable -verbose CWSDK1003I: Available SDKs : CWSDK1005I: SDK name: 1.6_32 - com.ibm.websphere.sdk.version.1.6_32=1.6 - com.ibm.websphere.sdk.bits.1.6_32=32 - com.ibm.websphere.sdk.location.1.6_32=${WAS_INSTALL_ROOT}/java - com.ibm.websphere.sdk.platform.1.6_32=linux - com.ibm.websphere.sdk.architecture.1.6_32=x86_32 -com.ibm.websphere.sdk.nativeLibPath.1.6_32=${WAS_INSTALL_ROOT}/lib/native/linux/x86_32/ CWSDK1001I: Successfully performed the requested managesdk task.

Loath answered 24/11, 2016 at 17:42 Comment(0)
N
0

The limitation also comes from the fact that for a 32 bit VM, the heap itself has to start at address zero if you want all those 4GB.

Think about it, if you want to reference something via:

0000....0001

i.e.: a reference that has this particular bits representation, it means you are trying to access the very first memory from the heap. For that to be possible, the heap has to start at address zero. But that never happens, it starts at some offset from zero:

    | ....               .... {heap_start .... heap_end} ... |
 --> (this can't be referenced) <--

Because heap never starts from address zero in an OS, there are quite a few bits that are never used from a 32 bits reference, and as such the heap that can be referenced is lower.

Nadanadab answered 2/5, 2020 at 3:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.