1

I have a Jar file that is ran in a server environment on demand, and I would like to limit the amount of memory that it uses so that multiple simultaneous instances can run comfortably. However, after setting the -Xmx512M parameter, it appears that Java is still using more memory than that. I am using the following command:

 java -Xmx512M -jar Reporter.jar /tmp/REPmKLs8K

However I can see that the process is using more than this:

Resource:     Virtual Memory Size
Exceeded:     1657 > 400 (MB)
Executable:   /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.91.x86_64/jre/bin/java
Command:      java -Xmx512M -jar Reporter.jar /tmp/REPmKLs8K

I'm not sure why this is, and it could potentially be an issue with the memory reporting software (ConfigServer Firewall). Has anyone experienced anything similar?

Alex Blundell
  • 2,084
  • 5
  • 22
  • 31
  • 1
    Note: virtual memory is virtual, not actual memory. I suggest you consider only the resident size without shared libraries. – Peter Lawrey Dec 17 '15 at 23:57

3 Answers3

0

-Xmx is the maximum heap size, not the process size.

See: What does Java option -Xmx stand for?

Community
  • 1
  • 1
ebyrob
  • 667
  • 7
  • 24
  • In that case, is there a way to specify that the whole Java process can only use X amount of memory? Or would this be done externally using a system command? – Alex Blundell Dec 17 '15 at 21:35
  • @AlexBlundell `ulimit` may work on UNIX systems. Are you using many many threads? That value is 3 times your heap limit. – ebyrob Dec 17 '15 at 21:37
  • It's actually just a single (main) thread. I'll give this a try now - thanks – Alex Blundell Dec 17 '15 at 21:38
  • @AlexBlundell if you reach the `ulimit` it will kill the process. It would be better to find out what memory outside the heap you program is using. – Peter Lawrey Dec 17 '15 at 23:56
0

-Xmx is used in order to specify the max heap allocation, but java needs more memory for JVM, pergem space (Java 7 and below), etc... You can see this post for memory structure

You can use tools like JVisualVM in order to profile the real memory usage in the JVM.

Francisco Hernandez
  • 2,378
  • 14
  • 18
  • 1
    Java8 does not have permgen. He might get a different result using that. – djangofan Dec 17 '15 at 21:37
  • actually JVisualVM does not show the native memory consumption only the heap, it will just make them more confused. –  Dec 17 '15 at 23:42
0

-Xmx doesn't control what you think it controls.

It only controls the JVM heap, not everything goes in the JVM heap, and the heap takes up way more native memory that what you specify for management and bookkeeping.

You can't control what you want to control, -Xmx only controls the Java Heap, it doesn't control consumption of native memory by the JVM, which is consumed completely differently based on implementation. The JVM uses up native memory in an entirely different way and it dependant on each JVM implementation and the OS it is running on.

From the following article Thanks for the Memory ( Understanding How the JVM uses Native Memory on Windows and Linux )

Maintaining the heap and garbage collector use native memory you can't control.

More native memory is required to maintain the state of the memory-management system maintaining the Java heap. Data structures must be allocated to track free storage and record progress when collecting garbage. The exact size and nature of these data structures varies with implementation, but many are proportional to the size of the heap.

and the JIT compiler uses native memory just like javac would

Bytecode compilation uses native memory (in the same way that a static compiler such as gcc requires memory to run), but both the input (the bytecode) and the output (the executable code) from the JIT must also be stored in native memory. Java applications that contain many JIT-compiled methods use more native memory than smaller applications.

and then you have the classloader(s) which use native memory

Java applications are composed of classes that define object structure and method logic. They also use classes from the Java runtime class libraries (such as java.lang.String) and may use third-party libraries. These classes need to be stored in memory for as long as they are being used. How classes are stored varies by implementation.

I won't even start quoting the section on Threads.

Plain and simple the JVM uses more memory than what is supplied in -Xms and -Xmx and the other command line parameters.

The Classloaders, and applications can have more than one, eat up lots of memory that isn't documented easily. The JIT eats up memory, trading space for time, which is a good trade off most of the time.

Some of the above links may refer to older Java versions; Java 8 handles garbage collection and memory allocation differently, but the general rules above apply.

Community
  • 1
  • 1