76 // }
77 //
78 // The check itself is simple:
79 // [1] CDSHeapVerifier::do_klass() collects all static fields
80 // [2] CDSHeapVerifier::do_entry() checks all the archived objects. None of them
81 // should be in [1]
82 //
83 // However, it's legal for *some* static fields to be referenced. The reasons are explained
84 // in the table of ADD_EXCL below.
85 //
86 // [A] In most of the cases, the module bootstrap code will update the static field
87 // to point to part of the archived module graph. E.g.,
88 // - java/lang/System::bootLayer
89 // - jdk/internal/loader/ClassLoaders::BOOT_LOADER
90 // [B] A final static String that's explicitly initialized inside <clinit>, but
91 // its value is deterministic and is always the same string literal.
92 // [C] A non-final static string that is assigned a string literal during class
93 // initialization; this string is never changed during -Xshare:dump.
94 // [D] Simple caches whose value doesn't matter.
95 // [E] Other cases (see comments in-line below).
96
97 CDSHeapVerifier::CDSHeapVerifier() : _archived_objs(0), _problems(0)
98 {
99 # define ADD_EXCL(...) { static const char* e[] = {__VA_ARGS__, nullptr}; add_exclusion(e); }
100
101 // Unfortunately this needs to be manually maintained. If
102 // test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedEnumTest.java fails,
103 // you might need to fix the core library code, or fix the ADD_EXCL entries below.
104 //
105 // class field type
106 ADD_EXCL("java/lang/ClassLoader$Holder", "scl"); // A
107 ADD_EXCL("java/lang/Module", "ALL_UNNAMED_MODULE", // A
108 "ALL_UNNAMED_MODULE_SET", // A
109 "EVERYONE_MODULE", // A
110 "EVERYONE_SET"); // A
111
112 // This is the same as java/util/ImmutableCollections::EMPTY_SET, which is archived
113 ADD_EXCL("java/lang/reflect/AccessFlag$Location", "EMPTY_SET"); // E
114
115 ADD_EXCL("java/lang/System", "bootLayer"); // A
276 void do_field(fieldDescriptor* fd) {
277 if (fd->field_type() != T_OBJECT) {
278 return;
279 }
280
281 oop static_obj_field = _ik->java_mirror()->obj_field(fd->offset());
282 if (static_obj_field != nullptr) {
283 if (_verifier->is_shared_secret_accessor(static_obj_field)) {
284 return;
285 }
286
287 Klass* field_type = static_obj_field->klass();
288 if (_exclusions != nullptr) {
289 for (const char** p = _exclusions; *p != nullptr; p++) {
290 if (fd->name()->equals(*p)) {
291 return;
292 }
293 }
294 }
295
296 if (fd->is_final() && java_lang_String::is_instance(static_obj_field) && fd->has_initial_value()) {
297 // This field looks like like this in the Java source:
298 // static final SOME_STRING = "a string literal";
299 // This string literal has been stored in the shared string table, so it's OK
300 // for the archived objects to refer to it.
301 return;
302 }
303 if (fd->is_final() && java_lang_Class::is_instance(static_obj_field)) {
304 // This field points to an archived mirror.
305 return;
306 }
307
308 if (field_type->is_instance_klass()) {
309 InstanceKlass* field_ik = InstanceKlass::cast(field_type);
310 if (field_ik->is_enum_subclass()) {
311 if (field_ik->has_archived_enum_objs() || ArchiveUtils::has_aot_initialized_mirror(field_ik)) {
312 // This field is an Enum. If any instance of this Enum has been archived, we will archive
313 // all static fields of this Enum as well.
314 return;
315 }
|
76 // }
77 //
78 // The check itself is simple:
79 // [1] CDSHeapVerifier::do_klass() collects all static fields
80 // [2] CDSHeapVerifier::do_entry() checks all the archived objects. None of them
81 // should be in [1]
82 //
83 // However, it's legal for *some* static fields to be referenced. The reasons are explained
84 // in the table of ADD_EXCL below.
85 //
86 // [A] In most of the cases, the module bootstrap code will update the static field
87 // to point to part of the archived module graph. E.g.,
88 // - java/lang/System::bootLayer
89 // - jdk/internal/loader/ClassLoaders::BOOT_LOADER
90 // [B] A final static String that's explicitly initialized inside <clinit>, but
91 // its value is deterministic and is always the same string literal.
92 // [C] A non-final static string that is assigned a string literal during class
93 // initialization; this string is never changed during -Xshare:dump.
94 // [D] Simple caches whose value doesn't matter.
95 // [E] Other cases (see comments in-line below).
96 //
97 // LIMITATION:
98 //
99 // CDSHeapVerifier can only check for problems with object identity. In the example above,
100 // if the Bar type has identity, the program's correctness requires that the identity
101 // of Foo.bar and Bar.bar to be equal. This requirement can be checked by CDSHeapVerifier.
102 //
103 // However, if Bar does not have identity (e.g., it's a value class, or is a primitive type),
104 // the program's correctness no longer requires that the identity of Foo.bar and Bar.bar
105 // to be equal (since they don't have an identity anymore). While the program's
106 // correctness may still have certain assumptions about Foo.bar and Bar.bar (such as the
107 // internal fields of these two values), such assumptions cannot be checked by CDSHeapVerifier.
108
109 CDSHeapVerifier::CDSHeapVerifier() : _archived_objs(0), _problems(0)
110 {
111 # define ADD_EXCL(...) { static const char* e[] = {__VA_ARGS__, nullptr}; add_exclusion(e); }
112
113 // Unfortunately this needs to be manually maintained. If
114 // test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedEnumTest.java fails,
115 // you might need to fix the core library code, or fix the ADD_EXCL entries below.
116 //
117 // class field type
118 ADD_EXCL("java/lang/ClassLoader$Holder", "scl"); // A
119 ADD_EXCL("java/lang/Module", "ALL_UNNAMED_MODULE", // A
120 "ALL_UNNAMED_MODULE_SET", // A
121 "EVERYONE_MODULE", // A
122 "EVERYONE_SET"); // A
123
124 // This is the same as java/util/ImmutableCollections::EMPTY_SET, which is archived
125 ADD_EXCL("java/lang/reflect/AccessFlag$Location", "EMPTY_SET"); // E
126
127 ADD_EXCL("java/lang/System", "bootLayer"); // A
288 void do_field(fieldDescriptor* fd) {
289 if (fd->field_type() != T_OBJECT) {
290 return;
291 }
292
293 oop static_obj_field = _ik->java_mirror()->obj_field(fd->offset());
294 if (static_obj_field != nullptr) {
295 if (_verifier->is_shared_secret_accessor(static_obj_field)) {
296 return;
297 }
298
299 Klass* field_type = static_obj_field->klass();
300 if (_exclusions != nullptr) {
301 for (const char** p = _exclusions; *p != nullptr; p++) {
302 if (fd->name()->equals(*p)) {
303 return;
304 }
305 }
306 }
307
308 if (!field_type->is_identity_class()) {
309 // See comment of LIMITATION above
310 // Any concrete value class will have a field ".null_reset" which holds an
311 // all-zero instance of the value class so it will not change between
312 // dump time and runtime.
313 return;
314 }
315
316 if (fd->is_final() && java_lang_String::is_instance(static_obj_field) && fd->has_initial_value()) {
317 // This field looks like like this in the Java source:
318 // static final SOME_STRING = "a string literal";
319 // This string literal has been stored in the shared string table, so it's OK
320 // for the archived objects to refer to it.
321 return;
322 }
323 if (fd->is_final() && java_lang_Class::is_instance(static_obj_field)) {
324 // This field points to an archived mirror.
325 return;
326 }
327
328 if (field_type->is_instance_klass()) {
329 InstanceKlass* field_ik = InstanceKlass::cast(field_type);
330 if (field_ik->is_enum_subclass()) {
331 if (field_ik->has_archived_enum_objs() || ArchiveUtils::has_aot_initialized_mirror(field_ik)) {
332 // This field is an Enum. If any instance of this Enum has been archived, we will archive
333 // all static fields of this Enum as well.
334 return;
335 }
|