1 /*
2  * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 #include "precompiled.hpp"
26 #include "classfile/classLoaderDataGraph.hpp"
27 #include "classfile/dictionary.hpp"
28 #include "classfile/javaClasses.hpp"
29 #include "classfile/systemDictionary.hpp"
30 #include "gc/shared/collectedHeap.hpp"
31 #include "memory/universe.hpp"
32 #include "oops/klass.inline.hpp"
33 #include "prims/jvmtiGetLoadedClasses.hpp"
34 #include "runtime/handles.inline.hpp"
35 #include "runtime/jniHandles.inline.hpp"
36 #include "runtime/thread.hpp"
37 #include "utilities/stack.inline.hpp"
38 
39 // The closure for GetLoadedClasses
40 class LoadedClassesClosure : public KlassClosure {
41 private:
42   Stack<jclass, mtInternal> _classStack;
43   JvmtiEnv* _env;
44   Thread*   _cur_thread;
45   bool      _dictionary_walk;
46 
extract(jclass * result_list)47   int extract(jclass* result_list) {
48     // The size of the Stack will be 0 after extract, so get it here
49     int count = (int)_classStack.size();
50     int i = count;
51 
52     // Pop all jclasses, fill backwards
53     while (!_classStack.is_empty()) {
54       result_list[--i] = _classStack.pop();
55     }
56 
57     // Return the number of elements written
58     return count;
59   }
60 
61   // Return current size of the Stack
get_count()62   int get_count() {
63     return (int)_classStack.size();
64   }
65 
66 public:
LoadedClassesClosure(JvmtiEnv * env,bool dictionary_walk)67   LoadedClassesClosure(JvmtiEnv* env, bool dictionary_walk) :
68       _env(env),
69       _cur_thread(Thread::current()),
70       _dictionary_walk(dictionary_walk) {
71   }
72 
do_klass(Klass * k)73   void do_klass(Klass* k) {
74     // Collect all jclasses
75     _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror())));
76     if (_dictionary_walk) {
77       // Collect array classes this way when walking the dictionary (because array classes are
78       // not in the dictionary).
79       for (Klass* l = k->array_klass_or_null(); l != NULL; l = l->array_klass_or_null()) {
80         _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, l->java_mirror())));
81       }
82     }
83   }
84 
get_result(JvmtiEnv * env,jint * classCountPtr,jclass ** classesPtr)85   jvmtiError get_result(JvmtiEnv *env, jint* classCountPtr, jclass** classesPtr) {
86     // Return results by extracting the collected contents into a list
87     // allocated via JvmtiEnv
88     jclass* result_list;
89     jvmtiError error = env->Allocate(get_count() * sizeof(jclass),
90                                (unsigned char**)&result_list);
91 
92     if (error == JVMTI_ERROR_NONE) {
93       int count = extract(result_list);
94       *classCountPtr = count;
95       *classesPtr = result_list;
96     }
97     return error;
98   }
99 };
100 
101 jvmtiError
getLoadedClasses(JvmtiEnv * env,jint * classCountPtr,jclass ** classesPtr)102 JvmtiGetLoadedClasses::getLoadedClasses(JvmtiEnv *env, jint* classCountPtr, jclass** classesPtr) {
103 
104   LoadedClassesClosure closure(env, false);
105   {
106     // To get a consistent list of classes we need MultiArray_lock to ensure
107     // array classes aren't created.
108     MutexLocker ma(MultiArray_lock);
109 
110     // Iterate through all classes in ClassLoaderDataGraph
111     // and collect them using the LoadedClassesClosure
112     MutexLocker mcld(ClassLoaderDataGraph_lock);
113     ClassLoaderDataGraph::loaded_classes_do(&closure);
114   }
115 
116   return closure.get_result(env, classCountPtr, classesPtr);
117 }
118 
119 jvmtiError
getClassLoaderClasses(JvmtiEnv * env,jobject initiatingLoader,jint * classCountPtr,jclass ** classesPtr)120 JvmtiGetLoadedClasses::getClassLoaderClasses(JvmtiEnv *env, jobject initiatingLoader,
121                                              jint* classCountPtr, jclass** classesPtr) {
122 
123   LoadedClassesClosure closure(env, true);
124   {
125     // To get a consistent list of classes we need MultiArray_lock to ensure
126     // array classes aren't created during this walk.
127     MutexLocker ma(MultiArray_lock);
128     MutexLocker sd(SystemDictionary_lock);
129     oop loader = JNIHandles::resolve(initiatingLoader);
130     // All classes loaded from this loader as initiating loader are
131     // requested, so only need to walk this loader's ClassLoaderData
132     // dictionary, or the NULL ClassLoaderData dictionary for bootstrap loader.
133     if (loader != NULL) {
134       ClassLoaderData* data = java_lang_ClassLoader::loader_data_acquire(loader);
135       // ClassLoader may not be used yet for loading.
136       if (data != NULL && data->dictionary() != NULL) {
137         data->dictionary()->all_entries_do(&closure);
138       }
139     } else {
140       ClassLoaderData::the_null_class_loader_data()->dictionary()->all_entries_do(&closure);
141     }
142     // Get basic arrays for all loaders.
143     Universe::basic_type_classes_do(&closure);
144   }
145 
146   return closure.get_result(env, classCountPtr, classesPtr);
147 }
148