34
34
#include " oops/instanceKlass.inline.hpp"
35
35
#include " runtime/mutexLocker.hpp"
36
36
37
- // Warning -- this is fragile!!!
38
- //
39
- // This is a hard-coded list of classes that are safe to preinitialize at dump time. It needs
40
- // to be updated if the Java source code changes.
41
- bool AOTClassInitializer::is_forced_preinit_class (InstanceKlass* ik) {
42
- if (!CDSConfig::is_dumping_invokedynamic ()) {
43
- return false ;
44
- }
45
-
46
- static const char * forced_preinit_classes[] = {
47
- " java/util/HexFormat" ,
48
- " jdk/internal/util/ClassFileDumper" ,
49
- " java/lang/reflect/ClassFileFormatVersion" ,
50
- " java/lang/Character$CharacterCache" ,
51
- " java/lang/invoke/Invokers" ,
52
- " java/lang/invoke/Invokers$Holder" ,
53
- " java/lang/invoke/MethodHandle" ,
54
- " java/lang/invoke/MethodHandleStatics" ,
55
- " java/lang/invoke/DelegatingMethodHandle" ,
56
- " java/lang/invoke/DelegatingMethodHandle$Holder" ,
57
- " java/lang/invoke/LambdaForm" ,
58
- " java/lang/invoke/LambdaForm$NamedFunction" ,
59
- " java/lang/invoke/ClassSpecializer" ,
60
- " java/lang/invoke/DirectMethodHandle" ,
61
- " java/lang/invoke/DirectMethodHandle$Holder" ,
62
- " java/lang/invoke/BoundMethodHandle$Specializer" ,
63
- " java/lang/invoke/MethodHandles$Lookup" ,
64
-
65
- // TODO:
66
- // This is needed since JDK-8338532. Without this, when
67
- // archived heap objects are used, the class init order is not
68
- // expected by the jdk/internal/constant bootstrap code and we
69
- // will get a null pointer exception.
70
- //
71
- // When bootstraping has intricated/fragile order, it's probably
72
- // better to archive all related classes in an initialized state
73
- // (i.e., take a snapshot). The existing approach in
74
- // heapShared::resolve_or_init_classes_for_subgraph_of() won't work.
75
- " jdk/internal/constant/PrimitiveClassDescImpl" ,
76
- " jdk/internal/constant/ReferenceClassDescImpl" ,
77
- " java/lang/constant/ConstantDescs" ,
78
- " sun/invoke/util/Wrapper" ,
79
-
80
- // TODO: these use java.lang.ClassValue$Entry which is a subtype of WeakReference
81
- // "java/lang/reflect/Proxy$ProxyBuilder",
82
- // "java/lang/reflect/Proxy",
83
-
84
- // TODO -- need to clear internTable, etc
85
- // "java/lang/invoke/MethodType",
86
-
87
- // TODO -- these need to link to native code
88
- // "java/lang/invoke/BoundMethodHandle",
89
- // "java/lang/invoke/BoundMethodHandle$Holder",
90
- // "java/lang/invoke/MemberName",
91
- // "java/lang/invoke/MethodHandleNatives",
92
- };
93
-
94
- for (const char * class_name : forced_preinit_classes) {
95
- if (ik->name ()->equals (class_name)) {
96
- if (log_is_enabled (Info, cds, init)) {
97
- ResourceMark rm;
98
- log_info (cds, init)(" Force initialization %s" , ik->external_name ());
99
- }
100
- return true ;
101
- }
102
- }
103
-
104
- return false ;
105
- }
106
-
107
37
// check_can_be_preinited() is quite costly, so we cache the results inside
108
38
// DumpTimeClassInfo::_can_be_preinited. See also AOTClassInitializer::reset_preinit_check().
109
39
bool AOTClassInitializer::check_can_be_preinited (InstanceKlass* ik) {
@@ -129,16 +59,17 @@ bool AOTClassInitializer::check_can_be_preinited(InstanceKlass* ik) {
129
59
}
130
60
}
131
61
132
- if (HeapShared::is_lambda_form_klass (ik) || is_forced_preinit_class (ik) ) {
62
+ if (HeapShared::is_lambda_form_klass (ik)) {
133
63
// We allow only these to have <clinit> or non-default static fields
134
- } else {
135
- if (ik->class_initializer () != nullptr ) {
136
- log_info (cds, init)(" cannot initialize %s (has <clinit>)" , ik->external_name ());
137
- return false ;
138
- }
139
- if (ik->is_initialized () && !has_default_static_fields (ik)) {
140
- return false ;
141
- }
64
+ return true ;
65
+ }
66
+
67
+ if (ik->class_initializer () != nullptr ) {
68
+ log_info (cds, init)(" cannot initialize %s (has <clinit>)" , ik->external_name ());
69
+ return false ;
70
+ }
71
+ if (ik->is_initialized () && !has_default_static_fields (ik)) {
72
+ return false ;
142
73
}
143
74
144
75
return true ;
@@ -254,24 +185,53 @@ bool AOTClassInitializer::can_archive_preinitialized_mirror(InstanceKlass* ik) {
254
185
255
186
if (ik->is_hidden ()) {
256
187
return HeapShared::is_archivable_hidden_klass (ik);
257
- } else if (ik->is_initialized ()) {
258
- if (ik->java_super () == vmClasses::Enum_klass ()) {
259
- return true ;
260
- }
261
- Symbol* name = ik->name ();
262
- if (name->equals (" jdk/internal/constant/PrimitiveClassDescImpl" ) ||
263
- name->equals (" jdk/internal/constant/ReferenceClassDescImpl" ) ||
264
- name->equals (" java/lang/constant/ConstantDescs" ) ||
265
- name->equals (" sun/invoke/util/Wrapper" )) {
188
+ }
189
+
190
+ if (ik->is_initialized () && ik->java_super () == vmClasses::Enum_klass ()) {
191
+ return true ;
192
+ }
193
+
194
+ Symbol* name = ik->name ();
195
+ if (name->equals (" jdk/internal/constant/PrimitiveClassDescImpl" ) ||
196
+ name->equals (" jdk/internal/constant/ReferenceClassDescImpl" ) ||
197
+ name->equals (" java/lang/constant/ConstantDescs" )) {
198
+ assert (ik->is_initialized (), " must be" );
199
+ // The above 3 classes are special cases needed to support the aot-caching of
200
+ // java.lang.invoke.MethodType instances:
201
+ // - MethodType points to sun.invoke.util.Wrapper enums
202
+ // - The Wrapper enums point to static final fields in the above 3 classes.
203
+ // E.g., ConstantDescs.CD_Boolean.
204
+ // - If we re-run the <clinit> of these 3 classes again during the production
205
+ // run, ConstantDescs.CD_Boolean will get a new value that has a different
206
+ // object identity than the value referenced by the the Wrapper enums.
207
+ // - However, Wrapper requires object identity (it allows the use of == to
208
+ // test the equality of ClassDesc, etc).
209
+ // Therefore, we must preserve the static fields of these 3 classes from
210
+ // the assembly phase.
211
+ return true ;
212
+ }
213
+ if (CDSConfig::is_dumping_invokedynamic ()) {
214
+ if (name->equals (" java/lang/Boolean$AOTHolder" ) ||
215
+ name->equals (" java/lang/Character$CharacterCache" ) ||
216
+ name->equals (" java/lang/invoke/BoundMethodHandle$Specializer" ) ||
217
+ name->equals (" java/lang/invoke/ClassSpecializer" ) ||
218
+ name->equals (" java/lang/invoke/DelegatingMethodHandle" ) ||
219
+ name->equals (" java/lang/invoke/DelegatingMethodHandle$Holder" ) ||
220
+ name->equals (" java/lang/invoke/DirectMethodHandle" ) ||
221
+ name->equals (" java/lang/invoke/DirectMethodHandle$AOTHolder" ) ||
222
+ name->equals (" java/lang/invoke/DirectMethodHandle$Holder" ) ||
223
+ name->equals (" java/lang/invoke/Invokers" ) ||
224
+ name->equals (" java/lang/invoke/Invokers$Holder" ) ||
225
+ name->equals (" java/lang/invoke/LambdaForm" ) ||
226
+ name->equals (" java/lang/invoke/LambdaForm$NamedFunction" ) ||
227
+ name->equals (" java/lang/invoke/LambdaForm$NamedFunction$AOTHolder" ) ||
228
+ name->equals (" java/lang/invoke/MethodHandle" ) ||
229
+ name->equals (" java/lang/invoke/MethodHandles$Lookup" ) ||
230
+ name->equals (" java/lang/invoke/MethodType$AOTHolder" ) ||
231
+ name->starts_with (" java/lang/invoke/ClassSpecializer$" )) {
232
+ assert (ik->is_initialized (), " must be" );
266
233
return true ;
267
234
}
268
- if (CDSConfig::is_dumping_invokedynamic ()) {
269
- if (name->equals (" java/lang/invoke/DirectMethodHandle$AOTHolder" ) ||
270
- name->equals (" java/lang/invoke/LambdaForm$NamedFunction$AOTHolder" ) ||
271
- name->equals (" java/lang/invoke/MethodType$AOTHolder" )) {
272
- return true ;
273
- }
274
- }
275
235
}
276
236
277
237
return AOTClassInitializer::can_be_preinited_locked (ik);
0 commit comments