< prev index next >

src/hotspot/share/cds/cdsHeapVerifier.cpp

Print this page

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) {}
< prev index next >