106 // tested for equality.
107 ADD_EXCL("java/util/HashSet", "PRESENT"); // E
108 ADD_EXCL("jdk/internal/loader/BuiltinClassLoader", "packageToModule"); // A
109 ADD_EXCL("jdk/internal/loader/ClassLoaders", "BOOT_LOADER", // A
110 "APP_LOADER", // A
111 "PLATFORM_LOADER"); // A
112 ADD_EXCL("jdk/internal/module/Builder", "cachedVersion"); // D
113 ADD_EXCL("jdk/internal/module/ModuleLoaderMap$Mapper", "APP_CLASSLOADER", // A
114 "APP_LOADER_INDEX", // A
115 "PLATFORM_CLASSLOADER", // A
116 "PLATFORM_LOADER_INDEX"); // A
117 ADD_EXCL("jdk/internal/module/ServicesCatalog", "CLV"); // A
118
119 // This just points to an empty Map
120 ADD_EXCL("jdk/internal/reflect/Reflection", "methodFilterMap"); // E
121
122 // Integer for 0 and 1 are in java/lang/Integer$IntegerCache and are archived
123 ADD_EXCL("sun/invoke/util/ValueConversions", "ONE_INT", // E
124 "ZERO_INT"); // E
125
126 # undef ADD_EXCL
127
128 ClassLoaderDataGraph::classes_do(this);
129 }
130
131 CDSHeapVerifier::~CDSHeapVerifier() {
132 if (_problems > 0) {
133 log_warning(cds, heap)("Scanned %d objects. Found %d case(s) where "
134 "an object points to a static field that may be "
135 "reinitialized at runtime.", _archived_objs, _problems);
136 }
137 }
138
139 class CDSHeapVerifier::CheckStaticFields : public FieldClosure {
140 CDSHeapVerifier* _verifier;
141 InstanceKlass* _ik;
142 const char** _exclusions;
143 public:
144 CheckStaticFields(CDSHeapVerifier* verifier, InstanceKlass* ik)
145 : _verifier(verifier), _ik(ik) {
183 // This field *may* be initialized to a different value at runtime. Remember it
184 // and check later if it appears in the archived object graph.
185 _verifier->add_static_obj_field(_ik, static_obj_field, fd->name());
186 }
187 }
188 };
189
190 // Remember all the static object fields of every class that are currently
191 // loaded.
192 void CDSHeapVerifier::do_klass(Klass* k) {
193 if (k->is_instance_klass()) {
194 InstanceKlass* ik = InstanceKlass::cast(k);
195
196 if (HeapShared::is_subgraph_root_class(ik)) {
197 // ik is inside one of the ArchivableStaticFieldInfo tables
198 // in heapShared.cpp. We assume such classes are programmed to
199 // update their static fields correctly at runtime.
200 return;
201 }
202
203 CheckStaticFields csf(this, ik);
204 ik->do_local_static_fields(&csf);
205 }
206 }
207
208 void CDSHeapVerifier::add_static_obj_field(InstanceKlass* ik, oop field, Symbol* name) {
209 StaticFieldInfo info = {ik, name};
210 _table.put(field, info);
211 }
212
213 inline bool CDSHeapVerifier::do_entry(oop& orig_obj, HeapShared::CachedOopInfo& value) {
214 _archived_objs++;
215
216 StaticFieldInfo* info = _table.get(orig_obj);
217 if (info != nullptr) {
218 if (value.orig_referrer() == nullptr && java_lang_String::is_instance(orig_obj)) {
219 // This string object is not referenced by any of the archived object graphs. It's archived
220 // only because it's in the interned string table. So we are not in a condition that
221 // should be flagged by CDSHeapVerifier.
222 return true; /* keep on iterating */
223 }
224 ResourceMark rm;
225 LogStream ls(Log(cds, heap)::warning());
226 ls.print_cr("Archive heap points to a static field that may be reinitialized at runtime:");
227 ls.print_cr("Field: %s::%s", info->_holder->name()->as_C_string(), info->_name->as_C_string());
228 ls.print("Value: ");
229 orig_obj->print_on(&ls);
230 ls.print_cr("--- trace begin ---");
231 trace_to_root(&ls, orig_obj, nullptr, &value);
232 ls.print_cr("--- trace end ---");
233 ls.cr();
234 _problems ++;
235 }
236
237 return true; /* keep on iterating */
238 }
239
240 class CDSHeapVerifier::TraceFields : public FieldClosure {
241 oop _orig_obj;
242 oop _orig_field;
243 outputStream* _st;
244
245 public:
246 TraceFields(oop orig_obj, oop orig_field, outputStream* st)
247 : _orig_obj(orig_obj), _orig_field(orig_field), _st(st) {}
|
106 // tested for equality.
107 ADD_EXCL("java/util/HashSet", "PRESENT"); // E
108 ADD_EXCL("jdk/internal/loader/BuiltinClassLoader", "packageToModule"); // A
109 ADD_EXCL("jdk/internal/loader/ClassLoaders", "BOOT_LOADER", // A
110 "APP_LOADER", // A
111 "PLATFORM_LOADER"); // A
112 ADD_EXCL("jdk/internal/module/Builder", "cachedVersion"); // D
113 ADD_EXCL("jdk/internal/module/ModuleLoaderMap$Mapper", "APP_CLASSLOADER", // A
114 "APP_LOADER_INDEX", // A
115 "PLATFORM_CLASSLOADER", // A
116 "PLATFORM_LOADER_INDEX"); // A
117 ADD_EXCL("jdk/internal/module/ServicesCatalog", "CLV"); // A
118
119 // This just points to an empty Map
120 ADD_EXCL("jdk/internal/reflect/Reflection", "methodFilterMap"); // E
121
122 // Integer for 0 and 1 are in java/lang/Integer$IntegerCache and are archived
123 ADD_EXCL("sun/invoke/util/ValueConversions", "ONE_INT", // E
124 "ZERO_INT"); // E
125
126 // Leyden-specific-begin
127 ADD_EXCL("java/lang/invoke/DirectMethodHandle", "LONG_OBJ_TYPE", // TEMP archive MethodTypes
128 "OBJ_OBJ_TYPE"); // TEMP archive MethodTypes
129
130 ADD_EXCL("sun/invoke/util/Wrapper", "FLOAT_ZERO", // ? there is a cache??
131 "DOUBLE_ZERO"); // ? there is a cache??
132
133 ADD_EXCL("java/lang/invoke/BoundMethodHandle$Specializer", "BMH_TRANSFORMS",
134 "SPECIES_DATA_ACCESSOR");
135 ADD_EXCL("java/lang/invoke/BoundMethodHandle", "SPECIALIZER");
136 ADD_EXCL("java/lang/invoke/DelegatingMethodHandle", "NF_getTarget");
137 ADD_EXCL("java/lang/invoke/MethodHandleImpl$ArrayAccessor", "OBJECT_ARRAY_GETTER",
138 "OBJECT_ARRAY_SETTER");
139 ADD_EXCL("java/lang/invoke/SimpleMethodHandle", "BMH_SPECIES");
140
141 ADD_EXCL("java/lang/invoke/StringConcatFactory", "NEW_ARRAY");
142 // Leyden-specific-end
143
144 # undef ADD_EXCL
145
146 ClassLoaderDataGraph::classes_do(this);
147 }
148
149 CDSHeapVerifier::~CDSHeapVerifier() {
150 if (_problems > 0) {
151 log_warning(cds, heap)("Scanned %d objects. Found %d case(s) where "
152 "an object points to a static field that may be "
153 "reinitialized at runtime.", _archived_objs, _problems);
154 }
155 }
156
157 class CDSHeapVerifier::CheckStaticFields : public FieldClosure {
158 CDSHeapVerifier* _verifier;
159 InstanceKlass* _ik;
160 const char** _exclusions;
161 public:
162 CheckStaticFields(CDSHeapVerifier* verifier, InstanceKlass* ik)
163 : _verifier(verifier), _ik(ik) {
201 // This field *may* be initialized to a different value at runtime. Remember it
202 // and check later if it appears in the archived object graph.
203 _verifier->add_static_obj_field(_ik, static_obj_field, fd->name());
204 }
205 }
206 };
207
208 // Remember all the static object fields of every class that are currently
209 // loaded.
210 void CDSHeapVerifier::do_klass(Klass* k) {
211 if (k->is_instance_klass()) {
212 InstanceKlass* ik = InstanceKlass::cast(k);
213
214 if (HeapShared::is_subgraph_root_class(ik)) {
215 // ik is inside one of the ArchivableStaticFieldInfo tables
216 // in heapShared.cpp. We assume such classes are programmed to
217 // update their static fields correctly at runtime.
218 return;
219 }
220
221 if (HeapShared::is_lambda_form_klass(ik)) {
222 // Archived lambda forms have preinitialized mirrors, so <clinit> won't run.
223 return;
224 }
225
226 CheckStaticFields csf(this, ik);
227 ik->do_local_static_fields(&csf);
228 }
229 }
230
231 void CDSHeapVerifier::add_static_obj_field(InstanceKlass* ik, oop field, Symbol* name) {
232 if (field->klass() == vmClasses::MethodType_klass() ||
233 field->klass() == vmClasses::LambdaForm_klass()) {
234 // LambdaForm and MethodType are non-modifiable and are not tested for object equality, so
235 // it's OK if the static fields are reinitialized at runtime with alternative instances.
236 // (TODO: double check is this is correct)
237 return;
238 }
239 StaticFieldInfo info = {ik, name};
240 _table.put(field, info);
241 }
242
243 inline bool CDSHeapVerifier::do_entry(oop& orig_obj, HeapShared::CachedOopInfo& value) {
244 _archived_objs++;
245
246 StaticFieldInfo* info = _table.get(orig_obj);
247 if (info != nullptr) {
248 if (value.orig_referrer() == nullptr && java_lang_String::is_instance(orig_obj)) {
249 // This string object is not referenced by any of the archived object graphs. It's archived
250 // only because it's in the interned string table. So we are not in a condition that
251 // should be flagged by CDSHeapVerifier.
252 return true; /* keep on iterating */
253 }
254 ResourceMark rm;
255
256 char* class_name = info->_holder->name()->as_C_string();
257 char* field_name = info->_name->as_C_string();
258 if (strstr(class_name, "java/lang/invoke/BoundMethodHandle$Species_") == class_name &&
259 strcmp(field_name, "BMH_SPECIES") == 0) {
260 // FIXME: is this really OK??
261 return true;
262 }
263 LogStream ls(Log(cds, heap)::warning());
264 ls.print_cr("Archive heap points to a static field that may be reinitialized at runtime:");
265 ls.print_cr("Field: %s::%s", class_name, field_name);
266 ls.print("Value: ");
267 orig_obj->print_on(&ls);
268 ls.print_cr("--- trace begin ---");
269 trace_to_root(&ls, orig_obj, nullptr, &value);
270 ls.print_cr("--- trace end ---");
271 ls.cr();
272 _problems ++;
273 }
274
275 return true; /* keep on iterating */
276 }
277
278 class CDSHeapVerifier::TraceFields : public FieldClosure {
279 oop _orig_obj;
280 oop _orig_field;
281 outputStream* _st;
282
283 public:
284 TraceFields(oop orig_obj, oop orig_field, outputStream* st)
285 : _orig_obj(orig_obj), _orig_field(orig_field), _st(st) {}
|