5

I am trying to enforce maximum memory a program can consume on a Unix system. I thought ulimit -v should do the trick. Here is a sample Java program I have written for testing :

import java.util.*;
import java.io.*;

public class EatMem {

  public static void main(String[] args) throws IOException, InterruptedException {
    System.out.println("Starting up...");
    System.out.println("Allocating 128 MB of Memory");
    List<byte[]> list = new LinkedList<byte[]>();
    list.add(new byte[134217728]); //128 MB
    System.out.println("Done....");
  }
}

By default, my ulimit settings are (output of ulimit -a) :

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 31398
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 31398
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

When I execute my java program (java EatMem), it executes without any problems. Now I try to limit max memory available to any program launched in the current shell to 512MB by launching the following command :

ulimit -v 524288

ulimit -a output shows the limit to be set correctly (I suppose):

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 31398
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 31398
virtual memory          (kbytes, -v) 524288
file locks                      (-x) unlimited

If I now try to execute my java program, it gives me the following error:

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

Ideally it should not happen as my Java program is only taking around 128MB of memory which is well within my specified ulimit parameters. If I change the arguments to my Java program as below:

java -Xmx256m EatMem

The program again works fine. While trying to give more memory than limited by ulimit like :

java -Xmx800m EatMem

results in expected error. Why the program fails to execute in the first case after setting ulimit ?

I have tried the above test on Ubuntu 11.10 and 12.0.4 with Java 1.6 and Java 7

1 Answer 1

3

ulimit -v sets the maximum address space a program can use. This includes all shared memory like libraries, thread stack space, direct memory etc. As the JVM isn't designed to run in a limited virtual memory environment like this it may not lay itself out in an optimal way. i.e. because virtual memory is normally very, very cheap. I suspect you have to set this value much higher to get the JVM to run.

BTW: The JVM allocates the maximum heap size on startup.


If I set ulimit -v 524288 and attempt to do

Runs ok

java -mx64m -version
java -mx128m -version
java -mx256m -version

Crashes with a failure to malloc

java -mx300m -version

Error occured during initialization of VM

java -mx400m -version
java -mx512m -version

This is more or less expected behaviour.

6
  • Can you say what they are? Sep 10, 2012 at 11:02
  • Sorry, re-writing the phrase as accidentally hit enter last time. Thanks @peter-lawrey for the explanation. But I am still not clear about why it still works when I pass -Xmx parameter explicitly ? BTW, When I try using ulimit -m 524288, it works as per the expectations i.e. when I try allocating 128MB of memory in the program, works without any issues but anything more than 512MB gets me an error.
    – Narinder Kumar
    Sep 10, 2012 at 11:05
  • I have added what I see from using ulimit -v. It behaves about as I would expect. Its worth remembering that the maximum heap size is NOT the maximum virtual memory used. Sep 10, 2012 at 11:19
  • So does it mean, if I have to control the maximum memory a Java program can consume, ulimit -v is not the correct approach? Is ulimit -m a better option or there is something else I should consider ?
    – Narinder Kumar
    Sep 10, 2012 at 12:05
  • 1
    which java version you used? I tried same commands you used and got Error occurred during initialization of VM Could not allocate metaspace: 1073741824 bytes My java version is 1.8.0_161
    – deFreitas
    May 7, 2018 at 21:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .