ART: Add GetLoadedClasses support

Add support to retrieve all loaded classes. Use the standard
ClassLoader callback infrastructure.

Bug: 31684578
Test: m test-art-host-run-test-907-get-loaded-classes
Change-Id: Ifb33cae27dc32602bcd8fd930d3c7eda02598c26
diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
index 05da585..ac8d5e1 100644
--- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
@@ -476,7 +476,8 @@
   }
 
   static jvmtiError GetLoadedClasses(jvmtiEnv* env, jint* class_count_ptr, jclass** classes_ptr) {
-    return ERR(NOT_IMPLEMENTED);
+    HeapUtil heap_util(&gObjectTagTable);
+    return heap_util.GetLoadedClasses(env, class_count_ptr, classes_ptr);
   }
 
   static jvmtiError GetClassLoaderClasses(jvmtiEnv* env,
diff --git a/runtime/openjdkjvmti/heap.cc b/runtime/openjdkjvmti/heap.cc
index 95d9a1d..745828a 100644
--- a/runtime/openjdkjvmti/heap.cc
+++ b/runtime/openjdkjvmti/heap.cc
@@ -19,7 +19,9 @@
 #include "art_jvmti.h"
 #include "base/macros.h"
 #include "base/mutex.h"
+#include "class_linker.h"
 #include "gc/heap.h"
+#include "jni_env_ext.h"
 #include "mirror/class.h"
 #include "object_callbacks.h"
 #include "object_tagging.h"
@@ -163,4 +165,48 @@
   return ERR(NONE);
 }
 
+jvmtiError HeapUtil::GetLoadedClasses(jvmtiEnv* env,
+                                      jint* class_count_ptr,
+                                      jclass** classes_ptr) {
+  if (class_count_ptr == nullptr || classes_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  class ReportClassVisitor : public art::ClassVisitor {
+   public:
+    explicit ReportClassVisitor(art::Thread* self) : self_(self) {}
+
+    bool operator()(art::mirror::Class* klass) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
+      classes_.push_back(self_->GetJniEnv()->AddLocalReference<jclass>(klass));
+      return true;
+    }
+
+    art::Thread* self_;
+    std::vector<jclass> classes_;
+  };
+
+  art::Thread* self = art::Thread::Current();
+  ReportClassVisitor rcv(self);
+  {
+    art::ScopedObjectAccess soa(self);
+    art::Runtime::Current()->GetClassLinker()->VisitClasses(&rcv);
+  }
+
+  size_t size = rcv.classes_.size();
+  jclass* classes = nullptr;
+  jvmtiError alloc_ret = env->Allocate(static_cast<jlong>(size * sizeof(jclass)),
+                                       reinterpret_cast<unsigned char**>(&classes));
+  if (alloc_ret != ERR(NONE)) {
+    return alloc_ret;
+  }
+
+  for (size_t i = 0; i < size; ++i) {
+    classes[i] = rcv.classes_[i];
+  }
+  *classes_ptr = classes;
+  *class_count_ptr = static_cast<jint>(size);
+
+  return ERR(NONE);
+}
+
 }  // namespace openjdkjvmti
diff --git a/runtime/openjdkjvmti/heap.h b/runtime/openjdkjvmti/heap.h
index fb9a216..b6becb9 100644
--- a/runtime/openjdkjvmti/heap.h
+++ b/runtime/openjdkjvmti/heap.h
@@ -28,6 +28,8 @@
   explicit HeapUtil(ObjectTagTable* tags) : tags_(tags) {
   }
 
+  jvmtiError GetLoadedClasses(jvmtiEnv* env, jint* class_count_ptr, jclass** classes_ptr);
+
   jvmtiError IterateThroughHeap(jvmtiEnv* env,
                                 jint heap_filter,
                                 jclass klass,