I was playing around with jmap
and found that simple "Hello World" Java program creates thousands of objects. Here is truncated list of objects Oracle JVM update 131 creates on startup:
num #instances #bytes class name
----------------------------------------------
1: 402 4903520 [I
2: 1621 158344 [C
3: 455 52056 java.lang.Class
4: 194 49728 [B
5: 1263 30312 java.lang.String
6: 515 26088 [Ljava.lang.Object;
7: 115 8280 java.lang.reflect.Field
8: 258 4128 java.lang.Integer
9: 94 3760 java.lang.ref.SoftReference
10: 116 3712 java.util.Hashtable$Entry
11: 126 3024 java.lang.StringBuilder
12: 8 3008 java.lang.Thread
13: 74 2576 [Ljava.lang.String;
14: 61 1952 java.io.File
15: 38 1824 sun.util.locale.LocaleObjectCache$CacheEntry
16: 12 1760 [Ljava.util.Hashtable$Entry;
17: 53 1696 java.util.concurrent.ConcurrentHashMap$Node
18: 23 1472 java.net.URL
19: 14 1120 [S
20: 2 1064 [Ljava.lang.invoke.MethodHandle;
21: 1 1040 [Ljava.lang.Integer;
22: 26 1040 java.io.ObjectStreamField
23: 12 1024 [Ljava.util.HashMap$Node;
24: 30 960 java.util.HashMap$Node
25: 20 800 sun.util.locale.BaseLocale$Key
I know that the JVM loads classes from JAR files and expect to see java.lang.Class
, java.lang.String
and [Ljava.lang.Object
. 258 java.lang.Integer
objects are clear tp me too: this is the Integer
cache.
But java.lang.reflect.Field
? Hashtable
? Many StringBuilder
s? java.util.concurrent.ConcurrentHashMap
? Where does this come from?
The program is pretty simple:
public class Test {
public static void main(String[] args) throws IOException {
System.out.println("Hello world");
System.in.read();
}
}
JVM details:
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
Ubuntu 16.04.
You can find the answer yourself by running the application with -XX:+TraceBytecodes
flag.
This flag is available in debug builds of HotSpot JVM.
Here is the detailed Flame Graph (clickable SVG) showing the stack traces where the allocated objects come from.
In my case the main sources of start-up allocations were
- URLClassLoader and Extension ClassLoader
- Locale cache
- UsageTrackerClient
- MetaIndex registry
- System Properties
- Charset initialization
P.S. The script used to generate the Flame Graph from TraceBytecodes output.