0

The metaspace requires is ~1GB

jenkins@android-build:~$ /var/lib/jenkins/tools/hudson.model.JDK/JDK_8u131/bin/java -version
Error occurred during initialization of VM
Could not allocate metaspace: 1073741824 bytes

Here are the memory limits for user jenkins

jenkins@android-build:~$ 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) 381421
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) 8000000
open files                      (-n) 65535
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) 381421
virtual memory          (kbytes, -v) 4000000
file locks                      (-x) unlimited

Trying to replicate an OutOfMemoryError situation, hence limiting the memory with ulimit

How much more memory do I need in order to run Java programs?

My program is configured to use max 4GB of heap

dexOptions {
        javaMaxHeapSize "4g"
        preDexLibraries true
    }

and 5GB Xmx gradle.properties

org.gradle.jvmargs=-Xmx5120M
ericn
  • 12,476
  • 16
  • 84
  • 127
  • 1
    Just to be sure. It's not running inside of a docker container? (java older than 11 can't properly detect memory limits if run within a container) – Mirek Pluta Dec 02 '21 at 14:07

1 Answers1

5

Your Jenkins environment has a strict limitation on the amount of virtual memory (-v) a process can use. Meanwhile, JVM tends to reserve a huge amount of virtual memory. Note: this is not the actual memory consumption, but just a reservation of the address space, which is practically unlimited on 64-bit systems, so JVM does not even attempt to be modest in such reservation by default.

Java process reserves virtual memory for Java Heap and for many other structures: Code Cache, Metaspace, Compressed Class Space, thread stacks etc. See the related answer for details.

You haven't set any JVM options, so the JVM by default reserves

  • 1/4 RAM for the Heap;
  • 1 GB for the Compressed Class Space;
  • 240 MB for the Code Cache;
  • 1 MB per each thread stack, and so on.

The above answer also mentions JVM options for limiting those structures.

Here is also an interesting post describing the experiment of reducing JVM memory usage.

Using jemalloc in place of the standard libc allocator, or limiting the number of allocator arenas using MALLOC_ARENA_MAX, allows to reduce virtual memory consumption even further.

For example, with the following command line options, JVM reserves less than 500 MB of virtual memory:

MALLOC_ARENA_MAX=2 java -Xmx100m -XX:ReservedCodeCacheSize=64m -XX:-UseCompressedClassPointers -Xss256k <args>

However, if possible, I'd suggest to set ulimit -v unlimited instead. As said above, virtual memory (unlike physical memory) is almost endless, so there is no much sense in limiting it.

apangin
  • 92,924
  • 10
  • 193
  • 247