为什么我的Oracle JVM为简单的"Hello World"程序创建了所有这些对象?

Dmi*_*kiy 9 java jvm

我一直在玩jmap,发现简单的"Hello World"Java程序创建了数千个对象.以下是Oracle JVM update 131在启动时创建的截断对象列表:

 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
Run Code Online (Sandbox Code Playgroud)

我知道JVM从JAR文件加载类并期望看到java.lang.Class,java.lang.String[Ljava.lang.Object.java.lang.Integer我也清楚了258个对象:这是Integer缓存.

但是java.lang.reflect.FieldHashtable?很多人StringBuilderjava.util.concurrent.ConcurrentHashMap?这是从哪里来的?

该程序非常简单:

public class Test {
    public static void main(String[] args) throws IOException {
        System.out.println("Hello world");
        System.in.read();
    }
}
Run Code Online (Sandbox Code Playgroud)

JVM详细信息:

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)
Run Code Online (Sandbox Code Playgroud)

Ubuntu 16.04.

apa*_*gin 22

您可以通过运行带有-XX:+TraceBytecodes标志的应用程序来自行找到答案.
此标志在HotSpot JVM的调试版本中可用.

下面是详细的Flame Graph(可点击的SVG),显示了分配对象来自的堆栈跟踪.

JDK启动分配

就我而言,启动分配的主要来源是

  • URLClassLoader和Extension ClassLoader
  • 区域设置缓存
  • UsageTrackerClient
  • MetaIndex注册表
  • 系统属性
  • Charset初始化

PS 用于从TraceBytecodes输出生成Flame Graph 的脚本.

  • 哇,这是一个很酷的直方图.信息量较少(但仍然通过观察顺序给出一些关于原因的胶水)是使用`-verbose:class`. (2认同)