Path: blob/master/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp
41145 views
/*1* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "classfile/classLoaderDataGraph.hpp"26#include "classfile/dictionary.hpp"27#include "classfile/javaClasses.hpp"28#include "gc/shared/collectedHeap.hpp"29#include "memory/universe.hpp"30#include "oops/klass.inline.hpp"31#include "prims/jvmtiGetLoadedClasses.hpp"32#include "runtime/handles.inline.hpp"33#include "runtime/jniHandles.inline.hpp"34#include "runtime/thread.hpp"35#include "utilities/stack.inline.hpp"3637// The closure for GetLoadedClasses38class LoadedClassesClosure : public KlassClosure {39private:40Stack<jclass, mtInternal> _classStack;41JvmtiEnv* _env;42Thread* _cur_thread;43bool _dictionary_walk;4445int extract(jclass* result_list) {46// The size of the Stack will be 0 after extract, so get it here47int count = (int)_classStack.size();48int i = count;4950// Pop all jclasses, fill backwards51while (!_classStack.is_empty()) {52result_list[--i] = _classStack.pop();53}5455// Return the number of elements written56return count;57}5859// Return current size of the Stack60int get_count() {61return (int)_classStack.size();62}6364public:65LoadedClassesClosure(JvmtiEnv* env, bool dictionary_walk) :66_env(env),67_cur_thread(Thread::current()),68_dictionary_walk(dictionary_walk) {69}7071void do_klass(Klass* k) {72// Collect all jclasses73_classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror())));74if (_dictionary_walk) {75// Collect array classes this way when walking the dictionary (because array classes are76// not in the dictionary).77for (Klass* l = k->array_klass_or_null(); l != NULL; l = l->array_klass_or_null()) {78_classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, l->java_mirror())));79}80}81}8283jvmtiError get_result(JvmtiEnv *env, jint* classCountPtr, jclass** classesPtr) {84// Return results by extracting the collected contents into a list85// allocated via JvmtiEnv86jclass* result_list;87jvmtiError error = env->Allocate(get_count() * sizeof(jclass),88(unsigned char**)&result_list);8990if (error == JVMTI_ERROR_NONE) {91int count = extract(result_list);92*classCountPtr = count;93*classesPtr = result_list;94}95return error;96}97};9899jvmtiError100JvmtiGetLoadedClasses::getLoadedClasses(JvmtiEnv *env, jint* classCountPtr, jclass** classesPtr) {101102LoadedClassesClosure closure(env, false);103{104// To get a consistent list of classes we need MultiArray_lock to ensure105// array classes aren't created.106MutexLocker ma(MultiArray_lock);107108// Iterate through all classes in ClassLoaderDataGraph109// and collect them using the LoadedClassesClosure110MutexLocker mcld(ClassLoaderDataGraph_lock);111ClassLoaderDataGraph::loaded_classes_do(&closure);112}113114return closure.get_result(env, classCountPtr, classesPtr);115}116117jvmtiError118JvmtiGetLoadedClasses::getClassLoaderClasses(JvmtiEnv *env, jobject initiatingLoader,119jint* classCountPtr, jclass** classesPtr) {120121LoadedClassesClosure closure(env, true);122{123// To get a consistent list of classes we need MultiArray_lock to ensure124// array classes aren't created during this walk.125MutexLocker ma(MultiArray_lock);126MutexLocker sd(SystemDictionary_lock);127oop loader = JNIHandles::resolve(initiatingLoader);128// All classes loaded from this loader as initiating loader are129// requested, so only need to walk this loader's ClassLoaderData130// dictionary, or the NULL ClassLoaderData dictionary for bootstrap loader.131if (loader != NULL) {132ClassLoaderData* data = java_lang_ClassLoader::loader_data_acquire(loader);133// ClassLoader may not be used yet for loading.134if (data != NULL && data->dictionary() != NULL) {135data->dictionary()->all_entries_do(&closure);136}137} else {138ClassLoaderData::the_null_class_loader_data()->dictionary()->all_entries_do(&closure);139}140// Get basic arrays for all loaders.141Universe::basic_type_classes_do(&closure);142}143144return closure.get_result(env, classCountPtr, classesPtr);145}146147148