Fix redefinition causing corrupt j.l.r.Field objects

During (non-structural) redefinition we change the dex-field-indexs of
all the ArtField's of the class being redefined. These ids are used by
the java/lang/reflect/Field class to avoid having to store a pointer
to the ArtField. This meant that when a class was redefined any
existing j.l.r.Field objects pointing to its fields are rendered
invalid, due to the dex_field_index no longer being present on the
class.

To fix this we simply walk the heap during class redefinition and
update any j.l.r.Field objects of the redefined class that we find.

Test: ./test.py --host
Bug: 147310999
Bug: 147338896
Change-Id: I3b038b4e669f8b7b4e804238248b4d03780ce2ca
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index dccc226..8a8fe30 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -105,6 +105,7 @@
 #include "mirror/dex_cache.h"
 #include "mirror/executable-inl.h"
 #include "mirror/field-inl.h"
+#include "mirror/field.h"
 #include "mirror/method.h"
 #include "mirror/method_handle_impl-inl.h"
 #include "mirror/object.h"
@@ -2560,6 +2561,7 @@
 }
 
 void Redefiner::ClassRedefinition::UpdateFields(art::ObjPtr<art::mirror::Class> mclass) {
+  std::unordered_map<uint32_t, uint32_t> dex_field_index_map;
   // TODO The IFields & SFields pointers should be combined like the methods_ arrays were.
   for (auto fields_iter : {mclass->GetIFields(), mclass->GetSFields()}) {
     for (art::ArtField& field : fields_iter) {
@@ -2572,10 +2574,33 @@
       const art::dex::FieldId* new_field_id =
           dex_file_->FindFieldId(*new_declaring_id, *new_name_id, *new_type_id);
       CHECK(new_field_id != nullptr);
+      uint32_t new_field_index = dex_file_->GetIndexForFieldId(*new_field_id);
+      // We need to keep track of the changes to the index so we can update any
+      // java.lang.reflect.Field objects that happen to be on the heap.
+      dex_field_index_map[field.GetDexFieldIndex()] = new_field_index;
       // We only need to update the index since the other data in the ArtField cannot be updated.
-      field.SetDexFieldIndex(dex_file_->GetIndexForFieldId(*new_field_id));
+      field.SetDexFieldIndex(new_field_index);
     }
   }
+  // walk the heap to update any java/lang/reflect/Field objects that refer to any of these fields.
+  // TODO We could combine this and do one heap-walk for all redefined classes.
+  art::ObjPtr<art::mirror::Class> reflect_field(art::GetClassRoot<art::mirror::Field>());
+  auto vis = [&](art::ObjPtr<art::mirror::Object> obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    // j.l.r.Field is a final class.
+    if (obj->GetClass() != reflect_field) {
+      return;
+    }
+    art::ObjPtr<art::mirror::Field> fld(art::down_cast<art::mirror::Field*>(obj.Ptr()));
+    // Only this class is getting new indexs.
+    if (fld->GetDeclaringClass() != mclass) {
+      return;
+    }
+    auto it = dex_field_index_map.find(fld->GetDexFieldIndex());
+    if (it != dex_field_index_map.end()) {
+      fld->SetDexFieldIndex</*kTransactionActive=*/false>(it->second);
+    }
+  };
+  driver_->runtime_->GetHeap()->VisitObjectsPaused(vis);
 }
 
 void Redefiner::ClassRedefinition::CollectNewFieldAndMethodMappings(