I'm looking into JIT behavior on a very simple block of code:
public class PlayWithAssembly {
public static void main(String[] args) {
Random random = new Random();
random.nextInt();
}
}
Actually, for the purpose of my question the content of the main
method is completely irrelevant. I'm running the following code using OpenJDK 10.0.1 on Ubuntu 16.04.5 and with the following command
java -Xbatch -XX:+PrintCompilation -XX:CompileThreshold=1000000 -cp target/classes com.xxx.playground.internal.bytecode.PlayWithAssembly
Since CompileThreshold
is set to a very high value I wouldn't expect JIT to compile anything, I would rather expect JVM to operate fully in interpreted mode in practice for this example. But when running the above command, I'm getting a following list of methods that have been compiled (all of them are part of JDK):
47 1 b 3 java.lang.StringLatin1::hashCode (42 bytes)
50 2 b 3 java.util.concurrent.ConcurrentHashMap::tabAt (22 bytes)
51 3 n 0 jdk.internal.misc.Unsafe::getObjectVolatile (native)
55 4 b 3 java.lang.Object::<init> (1 bytes)
56 5 b 3 java.lang.String::isLatin1 (19 bytes)
56 6 b 3 java.lang.String::hashCode (49 bytes)
57 7 b 3 java.lang.String::coder (15 bytes)
58 8 b 3 java.lang.Math::floorMod (10 bytes)
59 9 b 3 java.util.ImmutableCollections$SetN::probe (60 bytes)
62 10 b 1 java.util.ImmutableCollections$Set0::hashCode (2 bytes)
62 11 b 3 java.lang.String::equals (65 bytes)
64 12 b 1 java.util.Collections$EmptySet::hashCode (2 bytes)
65 13 b 3 java.lang.StringLatin1::equals (36 bytes)
66 14 b 3 java.util.Collections::emptySet (4 bytes)
66 15 b 3 java.lang.module.ModuleDescriptor$Exports::<init> (10 bytes)
67 16 b 4 java.lang.StringLatin1::hashCode (42 bytes)
71 1 3 java.lang.StringLatin1::hashCode (42 bytes) made not entrant
72 17 b 3 java.lang.module.ModuleDescriptor$Exports::hashCode (38 bytes)
73 18 b 3 java.util.Objects::equals (23 bytes)
73 19 b 3 java.util.Objects::requireNonNull (14 bytes)
74 20 b 3 java.util.AbstractCollection::<init> (5 bytes)
76 21 b 3 java.util.AbstractSet::<init> (5 bytes)
76 22 b 3 java.util.ImmutableCollections$AbstractImmutableSet::<init> (5 bytes)
77 23 b 1 java.lang.Object::<init> (1 bytes)
77 4 3 java.lang.Object::<init> (1 bytes) made not entrant
81 24 b 1 java.lang.module.ModuleDescriptor::name (5 bytes)
82 25 b 1 java.lang.module.ModuleReference::descriptor (5 bytes)
88 26 b 3 java.lang.String::charAt (25 bytes)
93 27 b 3 java.util.concurrent.ConcurrentHashMap::spread (10 bytes)
94 28 b 3 java.util.ImmutableCollections$SetN$1::hasNext (47 bytes)
95 29 b 3 java.util.ImmutableCollections$SetN$1::next (35 bytes)
96 30 b 3 java.util.Set::of (66 bytes)
98 31 b 1 java.util.KeyValueHolder::getKey (5 bytes)
99 32 b 1 java.util.KeyValueHolder::getValue (5 bytes)
100 33 b 3 java.util.ImmutableCollections$MapN::probe (64 bytes)
101 34 b 3 java.util.KeyValueHolder::<init> (21 bytes)
102 35 b 3 java.util.ImmutableCollections$MapN::get (21 bytes)
103 36 n 0 java.lang.Object::hashCode (native)
103 37 b 3 jdk.internal.module.ModuleReferenceImpl::hashCode (56 bytes)
105 38 b 3 java.util.HashMap::hash (20 bytes)
106 39 !b 3 java.util.concurrent.ConcurrentHashMap::putVal (432 bytes)
112 40 n 0 jdk.internal.misc.Unsafe::compareAndSetLong (native)
112 41 b 3 java.util.concurrent.ConcurrentHashMap::putIfAbsent (8 bytes)
112 42 b 1 java.lang.module.ResolvedModule::reference (5 bytes)
113 43 b 3 java.util.concurrent.ConcurrentHashMap::addCount (289 bytes)
115 2 3 java.util.concurrent.ConcurrentHashMap::tabAt (22 bytes) made not entrant
115 39 ! 3 java.util.concurrent.ConcurrentHashMap::putVal (432 bytes) made not entrant
115 44 b 3 jdk.internal.misc.Unsafe::getObjectAcquire (7 bytes)
116 45 b 3 java.util.concurrent.ConcurrentHashMap::tabAt (22 bytes)
116 46 n 0 jdk.internal.misc.Unsafe::compareAndSetObject (native)
117 47 b 3 java.util.concurrent.ConcurrentHashMap$Node::<init> (20 bytes)
117 48 !b 3 java.util.concurrent.ConcurrentHashMap::putVal (432 bytes)
120 49 b 3 java.util.concurrent.ConcurrentHashMap::casTabAt (21 bytes)
122 50 b 3 java.util.HashMap::getNode (148 bytes)
124 51 b 3 java.lang.String::length (11 bytes)
125 52 b 3 java.lang.StringLatin1::canEncode (13 bytes)
126 53 b 3 java.util.HashMap::put (13 bytes)
127 54 n 0 java.lang.System::arraycopy (native) (static)
128 55 b 3 java.util.HashMap$Node::<init> (26 bytes)
128 56 b 3 java.util.HashMap::newNode (13 bytes)
129 57 b 3 java.util.HashMap::afterNodeInsertion (1 bytes)
129 58 b 3 java.util.Optional::ofNullable (15 bytes)
131 59 b 3 java.util.HashMap::get (23 bytes)
132 60 b 3 java.util.HashMap::putVal (300 bytes)
135 61 b 1 java.lang.module.ModuleDescriptor$Exports::source (5 bytes)
135 62 b 1 java.util.Collections$1::hasNext (5 bytes)
136 63 b 3 java.lang.module.ResolvedModule::name (11 bytes)
137 64 b 3 java.util.HashSet::add (20 bytes)
137 65 b 1 java.util.Collections$EmptySet::isEmpty (2 bytes)
138 66 b 3 java.lang.module.ResolvedModule::hashCode (16 bytes)
139 67 b 3 java.lang.module.ModuleDescriptor$Exports::isQualified (18 bytes)
140 68 b 1 java.lang.module.ModuleDescriptor::isAutomatic (5 bytes)
140 69 b 3 java.util.AbstractMap::<init> (5 bytes)
141 70 b 1 java.lang.module.ModuleDescriptor$Exports::targets (5 bytes)
141 71 b 1 java.lang.module.ResolvedModule::configuration (5 bytes)
142 72 b 3 java.util.HashMap::<init> (11 bytes)
142 73 b 3 java.util.ImmutableCollections$Set2$1::hasNext (14 bytes)
143 74 b 4 java.util.ImmutableCollections$SetN$1::hasNext (47 bytes)
148 28 3 java.util.ImmutableCollections$SetN$1::hasNext (47 bytes) made not entrant
149 75 b 1 java.util.ImmutableCollections$Set1::size (2 bytes)
150 76 b 3 java.lang.Math::min (11 bytes)
152 77 b 3 java.util.AbstractCollection::isEmpty (13 bytes)
153 78 b 4 java.lang.String::hashCode (49 bytes)
160 6 3 java.lang.String::hashCode (49 bytes) made not entrant
162 79 b 3 java.util.Map::entry (10 bytes)
165 80 b 1 java.lang.module.ModuleDescriptor::isOpen (5 bytes)
167 81 b 1 java.util.HashMap::afterNodeInsertion (1 bytes)
167 57 3 java.util.HashMap::afterNodeInsertion (1 bytes) made not entrant
168 82 b 3 jdk.internal.module.ModuleBootstrap$2::hasNext (30 bytes)
169 83 b 3 java.util.HashMap::resize (356 bytes)
171 84 b 3 java.util.Collections$UnmodifiableCollection$1::hasNext (10 bytes)
172 85 b 3 jdk.internal.module.ModuleBootstrap$2::next (52 bytes)
173 86 b 3 java.util.HashMap::putIfAbsent (13 bytes)
174 87 n 0 java.lang.Module::addExportsToAllUnnamed0 (native) (static)
175 88 b 1 java.lang.Module::getDescriptor (5 bytes)
182 78 4 java.lang.String::hashCode (49 bytes) made not entrant
185 89 b 3 java.lang.StringLatin1::indexOf (61 bytes)
187 23 1 java.lang.Object::<init> (1 bytes) made not entrant
195 90 b 1 java.lang.Object::<init> (1 bytes)
197 91 b 3 java.lang.String::hashCode (49 bytes)
I was trying to match these methods with the list of intrinsics but it does not match, so my questions are: why these methods are compiled (and others are not), and do I have any control over it?
From the documentation of -XX:CompileThreshold
:
This option is ignored when tiered compilation is enabled;
see the option-XX:-TieredCompilation
.
So when specifying -XX:-TieredCompilation
, most of these entries will go away, however, some entries may still be exempted from the counter based compilation decision.