We’ve recently been performing some memory optimisations on OneMusicAPI to improve the performance of the service.
One aspect we explored was the memory use of cached code. We use a lot of Scala in the codebase and were concerned that many classes were being generated, cached, and using up memory space.
So we broke out the tools and dived into some lesser-known Java tools to analyse how much memory is being consumed in the code cache.
jcmd command, among other things,
provides a listing of the classes that are stored in code cache.
We can generate the compiled code listing using the
jcmd <pid> Compiler.codelist command. The output of the above command looks like this (truncated for brevity):
$ jcmd <pid> Compiler.codelist <pid>: 3 0 0 jdk.internal.misc.Unsafe.getObjectVolatile(Ljava/lang/Object;J)Ljava/lang/Object; [0x00007f4f4c438010, 0x00007f4f4c4381c0 - 0x00007f4f4c438440] 14 0 0 jdk.internal.misc.Unsafe.compareAndSetLong(Ljava/lang/Object;JJJ)Z [0x00007f4f4c438490, 0x00007f4f4c438640 - 0x00007f4f4c438850] 16 0 0 jdk.internal.misc.Unsafe.compareAndSetObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z [0x00007f4f4c438890, 0x00007f4f4c438a40 - 0x00007f4f4c438c78] 23 4 0 java.lang.Object.<init>()V [0x00007f4f4c438c90, 0x00007f4f4c438e20 - 0x00007f4f4c438e98] 20 1 0 java.lang.module.ModuleReference.descriptor()Ljava/lang/module/ModuleDescriptor; [0x00007f4f4c438f10, 0x00007f4f4c4390c0 - 0x00007f4f4c439190] 21 1 0 java.lang.module.ModuleDescriptor.name()Ljava/lang/String; [0x00007f4f4c439210, 0x00007f4f4c4393c0 - 0x00007f4f4c439490]
The source code for the C++ code that generates the list is available on GitHub, but we weren’t able to find any documentation or web pages describing what the output columns represented. However, by referring to the source code, one can see that each line has the following format:
compile_id comp_level get_state method_name [header_begin, code_begin - code_end]
The values for
code_end are memory addresses in hexadecimal (base 16).
We weren’t able to find documentation about these fields, and given that we aren’t C++ programmers, it was difficult to go through the code base looking for clues. For our use-case, we only needed to check the total size of the compiled code for each base package, so the column names were enough.
Using the first line of the output above as an example, we can calculate the code size as follows:
0x00007f4f4c438440-0x00007f4f4c4381c0gives 640 (in base 10).
code_beginvalue might be something like
0x000012ffffffffff, making the final code size result negative, but we have not encountered that.]
HEX2DEC. Continuing the above example,
4f4c4381c0becomes 340581908928 and
Coming across a question that doesn’t have an answer on the web is a rare occurrence these days. While most people using
jcmd Compiler.codecache will be able to figure out the answer themselves, we hope that this blog post ends up being helpful to someone like us.
By Waqqas Dadabhoy