Tomcat: adjust memory proportions - java

I have a Tomcat instance running on a Windows 2008 Server with 4GB of RAM. The server is dedicated to this one application, so I would quite like to be able to dedicate most of the RAM to Tomcat. My Tomcat setup currently has the following java options:
-Xms256m
-Xmx1600m
I'd like to increase the amount of RAM, preferably up to about 3GB (obviously I know how to do that, just increase the -Xmx value). However, Tomcat refuses to start up if I increase the maximum heap space beyond 1600MB. Several websites that I have read say that Tomcat cannot use more than 40% of the available RAM, which seems consistent with what I'm seeing.
Is there a way of increasing the proportion of memory that Tomcat can use, so that I can increase the amount of memory that Tomcat can use?

Your issue was probably OS related, not Tomcat / Java. The Windows OS limits the memory allocation of a 32-bit process to 2 GiB in total (by default).
The reason why it only allowed you to allocate around 1.5 GiB heap space is because there is also other memory allocated to the process (the JVM / library overhead, perm gen space etc.).
Why does 32-bit Windows impose a 2 GB process address space limit, but 64-bit Windows impose a 4GB limit?
Other modern operating systems [cough Linux] allow 32-bit processes to use all (or most) of the 4 GiB addressable space.
That said, 64-bit Windows OS's can be configured to increase the limit of 32-bit processes to 4 GiB (3 GiB on 32-bit):
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366778(v=vs.85).aspx
However, as you've rightly done, the best solution is to use a 64-bit JVM with your 64-bit OS. Terabyte heaps anyone:
Max memory for 64bit Java :D

Despite having a 64 bit server I only had 32 bit Java/Tomcat installed. I uninstalled Java and Tomcat and installed 64 bit versions and everything worked fine. it seems that the issue was that 32 bit Java can only address 1.5 GB.

Related

Anyway to set more max ram to Tomcat 32bit? Why there is hard wall limit at 1GB and 1.6GB

Something wierd seems to be going on... I have an application on tomcat that used to be on a physical windows server 2008 standard 32-bit which I p2v'd with vmware converter over as a VM. I'm upgrading the server to windows server 2008 r2 64bit and instead of doing an inplace, I'm just building another one up and doing parallel side by side, and its a fresh VM from the start, no p2v stuff....
The strange part is I was able to set a max memory in the tomcat9w.exe configuration tool to about 1600 Megabytes and that was the hitting of the wall on that setup (the original physical one that I p2v'd to a VM), I can set less ram, but I cannot set it more than 1600 otherwise when I try to start the tomcat service in services.msc it will just crap outs.
So my thinking was since I have to stay on 32-bit of tomcat and 32-bit of Java JVM anyhow (long story...) that it might be better to put it in a 64-bit OS (server 2008r2) rather than the standard 32bit of server 2008. Long story short, from a fresh VM, on this box I'm only able to set a max total ram in tomcatw as around 1000 m (1GB) and if I set anymore it will not start, as in I cannot get tomcat service to start... so the wall is around 1GB...
As a test, I installed the tomcat (zip extract, not using msi or exe installer) to my own client workstation laptop running the latest windows 10 1809 etc and once again I hit the 1GB wall and cannot even get it to go up to 1.6GB, even though I have like 16GB ram on my laptop machine...
I have googled this for a long time and apparently it has to do with the way the operating system itself (in this case windows, be it windows server 2008 std, 2008 r2, or win10 etc) handles per process memory limitations and thread memory allocations that by default only allow around 1.5 to 2 g of ram per process and that this is what is constraining the tomcat apache jvm and not the programs itself....
But if this is indeed an OS difference, I checked on my original 32bit server2008 std, the one that I did P2V, and it didn't have anything special set in the boot.ini or any bcdedit parameters that allow it to see more ram per process nor anything like a /3GB flag etc etc
The only other thing I can think of is that maybe there is a difference between a VM and a physical raw bare metal box in how it allocates ram, and that I can get more contigous memory that tomcat/jvm requires when running on a 32bit OS on a physical box as opposed to and compared to a 64bit OS in a VM?
Why is it I can get the exact same version of Tomcat (bit by bit the same) to handle up to 1600m in 32bit version of server 2008 but on server 2008r2 64bit or even server 2016 64bit I can only get tomcat to do up to around 1GB total max? They are both using the same Java version jvm etc etc etc
See https://www.oracle.com/technetwork/java/hotspotfaq-138619.html#gc_heap_32bit:
Why can't I get a larger heap with the 32-bit JVM?
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.
As of Java SE 6, the Windows /3GB boot.ini feature is not supported.
If your application requires a very large heap you should use a 64-bit VM on a version of the operating system that supports 64-bit applications. See Java SE Supported System Configurations for details.

Java JVM Heap Size

I have an application that on launch requests a specific amount of RAM using the following command.
java -Xms512m -Xmx985m -jar someJarfile.jar
This command fails to run on my computer with 8.0GB of RAM because it can not create an object heap of the specified size. If I lower the max range to something below 700MB it works fine.
What is even stranger is that even doing a simple java -Xmx768m -version fails when the -Xmx flag value exceeds 700m. I am trying to run it with Java 1.7Uu67 32-bit(that is what the jar was built with) and even newer versions of Java 1.7 and event Java 1.8. I would understand if the max heap was higher and I was using 32bit, but it is not above the ~1.4GB cap of 32-bit java
Is there a configuration parameter that I am missing somewhere that would be causing this, some sort of software that may be interfering? It does not make sense to me as to why I can not allocate 700MB of RAM on a machine with 8.0GB of RAM. I
I should also note that there are no other processes running that are taking up all of my RAM. It is a fresh install of Windows 7.
While 700 MB is pretty low, it is not surprising.
The 32-bit Windows XP emulator in Windows works the same way as Windows XP with all it's limitations. It means you lose 2 GB or a potential 4 GB to the OS. This means programs already running use up virtual memory space. Also if your program uses shared libraries or off heap storage like direct memory and memory mapped files this will means you lose virtual memory for the heap. Effectively you are limited to 1.4 GB of virtual memory for your applications no matter how much memory you actually have.
The simple way around this it to use the 64-bit JVM which runs in your 64-bit OS and is also limited but instead to 192 TB of virtual memory on Windows.
You should try using a 64 bit Java Runtime. It is probably the case that there is no 985 MB large one-piece memory chunk free within the 32-bit address space of your computer (the 32 bit address space 4GB). When you use a 64 bit Java Runtime, Java can allocate the memory within the 64 bit address space, in which the free memory is much more likely to be available.
It doesn't matter that your JAR file was built using a 32 bit version.
The answer to your question may lie in the fact that Windows tries and fails to find a contiguous block of memory that is large enough: see http://javarevisited.blogspot.nl/2013/04/what-is-maximum-heap-size-for-32-bit-64-JVM-Java-memory.html. (Though this suggests that other processes are hogging memory, which seems to be contradicted by your last remark.)

Java Heap Space and the RAM

I have a question that bothered me after reading an article on analyzing thread dumps. There was one paragraph which mentioned that the logical maximum heap size in a 32-Bit JVM is 4GB.
This link states that the maximum heap size on a 32-bit Windows machine will be around 1.4 - 1.6 GB.
My question is, say if you have RAM of say around 8GB, does this mean i can only utilize 1.4-1.6 GB of it if i were to you a 32-bit JVM? And what will be the maximum size allowed for a 64bit JVM?
Appreciate your help regarding this as i am confused on the same.
specifically on windows, the reason is a combination of the implementation of hotspot (the sun/oracle JVM) and windows dlls.
32-bit code has access to a 4GB virtual address space (there are extensions that allow more but i wont be going into those).
on 32-bit windows the upper 2GB of this virtual address space are reserved for operating sysem use (some versions of the OS accept the /3GB flag as a boot parameter to allow for 3GB of user-accessible space).
also, any libraries (*.dlls) you use are mapped into parts of this address space. by default the windows base *.dll files are loaded at the ~1.6 GB mark (differs slightly by OS version and patch level)
on top of all this, the hotspot JVM only supports allocating a single, continuous, chunk of memory for use as heap space.
so, if you try and picture this in your head, you'll see that you have a free area of ~2GB with a "wall" of windows *.dlls loaded at ~1.6GB. this is the logic behind that figure. it also means that even if you provide the /3GB flag the sun/oracle JVM will not be able to make use of it. some other VMs are better at handling a fragmented heap - like the jrockit VM
you could also try rebasing windows dlls so that they load into higher memory addresses and squeeze some more usable heap space, but the process is fragile.
also note that its very possible that drivers/applications loaded on a particular machines (like anti virus software) will inject their own *.dlls into a java process, and those dlls can be loaded at ever lower memory addresses, further shrinking your usable heap space.
on 64bit versions of windows the addressable limit is 8-128TB and the physical limit stands at 64TB right now
2^32 = 4GB is the max total memory you can address with 32 bits.
The JVM only gets 1.4-1.6GB on 32 bit machines because you still have to accomodate the operating system.
2^64 = (2^32)^2 is the max total memory you can address with 64 bits. As you can see, it's a much larger number.
jvm and also os use paging memory managment system that obtain 4G virtual memory for us in
32bit os systems
but if you have 8G ram you must use 64 bit version of os for maximum performance of os
It depends on your operating system, 32 bit versions of MacOS X and Linux have some ability to access more than 4GB in the kernel but still limit processes to 4GB. Other operating systems may restrict process memory further since they need part of the 4GB for themselves. In general you want to avoid swapping out your JVM to VM so you need to know how much free memory you system has.

Java Heap Space - Cannot make large enough

I am trying to set the Xmx parameter when starting up a program. If I set it to 1408M, the JRE starts up fine. If I set it to 1536M, I get
"Could not create the java virtual machine".
I understand that it's trying to reserve consecutive memory space, but the machine I'm running on has 16GB of RAM and 13GB of that is currently free. The program I'm running is running out of heap space and crashing on me. Is there anything I can do to fix this?
Use a 64bit JVM. The 32bit JVM is limited (depending on the OS) to at most 3 GByte (on linux I have a limitation of about 1.5 GByte).
32-bit JVMs are limited to roughly 1.5 GB of heap space due to addressing constraints and the need for memory for other reasons. On Windows 2 GB is assigned to the process, and 0.5 is used for non-heap memory. If you can use PAE on Windows Server or possibly Linux, you can address up to 3 or 4 GB, respectively.
Otherwise use a 64-bit JVM.

Why is there such a big difference in memory use of a Java application in Windows XP 32 vs Windows 7 64

I have a little Java application that I wrote for recording my work activities. Since I have it open all day, every day, one of the things that originally concerned me as to choice of language is the amount of memory it would use.
Happily, under Windows XP I it would typically consume about 5 MB when minimized and 12 or so when maximized, and happily runs with -Xmx5M (memory consumption according to Windows Task Manager).
When I upgraded my home PC with newer hardware, and at the same time, to Windows 7 64, (although I installed and am using the 32 bit JVM), I immediately noted that the JVM for this application now reports 68 MB+ always... and that's with -Xmx5M -Xss16K, according to Task Manager's "Working Set".
Both the old and new machines had/have 4 GB of RAM, of which 512 MB is used by video. Both were running recent builds of Java 6 - about update 15 for WinXP, and now update 24 for Win7. The application footprint on disk is 70 K in 12 classes. Moreover, my work computer is still Windows XP, running Java 6_24, and it shows about 12 MB for this identical application - and by identical I mean literally that, since the two systems are sync'd for all my development tools.
As a developer, I need to understand the reasons why my applications appear to chew up so much memory.
Can anyone shed some light on this, and suggest how to meaningfully reduce the memory footprint for a Java 6 application?
Edit
The answer may be in an excessive PermGen size. According to JVisualVM, I have a heap of:
Size: 5.2 MB, Used: 4.3 MB (peak) and Allocated 6.2 MB.
but for the PermGen
Size: 12.5 MB, Used: 4.6 MB (peak) and Allocated 67.1 MB.
So is it possible that the 68 MB shown in Task Manager in Win 7 is simply requested but unassigned virtual memory?
EDIT 2
Reducing PermGen to 12 MB had no effect on the process RAM, but JVisualVM did show it reduced (apparently 12 MB constitutes some sort of minimum, because going lower than that had no effect in JVVM).
The 64 bit OS uses 64 bits as the size of pointers while a 32 bit OS uses 32 bits. That might just be one of the reasons though.
Remember that everything in Java is a pointer (for the most part) so when switching to a 64 bit machine, with 64 bit memory addresses, your pointers double in size.
There is an option in the JVM (-XX:+UseCompressedOops) to turn on compressed object pointers. This will put your memory usage near the levels you saw on 32 bit machines.
For the 64-bit JVM you can specify an option that will reduce the overhead of 64-bit addressing. As long as the heap is under 32GB it can essentially compress the pointers back to 32-bit. In a typical Java application this saves about 40% of the memory. See Compressed oops in the Hotspot JVM for more details. Here's the option for it:
-XX:+UseCompressedOops
Note that if you use a 32-bit JVM on a 64-bit OS that you won't pay the overhead of 64-bit memory addresses (although there's a different overhead to pay there in translation, yet it's very minor).
I believe that Windows 7 doesn't report memory use the same as XP either (I don't have a reference offhand though). So for a fair comparison of 32-bit vs 64-bit you need to run both on the same version of Windows.
This has nothing to do with the operating system being 64-bit - Windows XP and Windows 7 use RAM in very different ways.
Because of this, Windows 7 will almost always report all programs as using more memory than Windows XP did. Don't worry about this - this is just a result of Windows 7 using your memory the way it should be: as a cache.
While it's not the whole story, the PermGen size is 30% larger on 64-bit plaforms:
-XX:MaxPermSize - Size of the Permanent Generation.
[5.0 and newer: 64 bit VMs are scaled
30% larger; 1.4 amd64: 96m; 1.3.1
-client: 32m.]
Java 6 HotSpot VM Options

Categories