Path: blob/master/src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp
41152 views
/*1* Copyright (c) 2012, 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/javaClasses.inline.hpp"26#include "classfile/symbolTable.hpp"27#include "classfile/systemDictionary.hpp"28#include "jfr/jni/jfrJavaSupport.hpp"29#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"30#include "jfr/support/jfrJdkJfrEvent.hpp"31#include "memory/allocation.inline.hpp"32#include "memory/resourceArea.hpp"33#include "oops/instanceKlass.hpp"34#include "oops/klass.inline.hpp"35#include "runtime/handles.inline.hpp"36#include "runtime/thread.inline.hpp"37#include "utilities/stack.inline.hpp"3839static jobject empty_java_util_arraylist = NULL;4041static oop new_java_util_arraylist(TRAPS) {42DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));43JavaValue result(T_OBJECT);44JfrJavaArguments args(&result, "java/util/ArrayList", "<init>", "()V", CHECK_NULL);45JfrJavaSupport::new_object(&args, CHECK_NULL);46return result.get_oop();47}4849static const int initial_array_size = 64;5051template <typename T>52static GrowableArray<T>* c_heap_allocate_array(int size = initial_array_size) {53return new (ResourceObj::C_HEAP, mtTracing) GrowableArray<T>(size, mtTracing);54}5556static bool initialize(TRAPS) {57static bool initialized = false;58if (!initialized) {59assert(NULL == empty_java_util_arraylist, "invariant");60const oop array_list = new_java_util_arraylist(CHECK_false);61empty_java_util_arraylist = JfrJavaSupport::global_jni_handle(array_list, THREAD);62initialized = empty_java_util_arraylist != NULL;63}64return initialized;65}6667/*68* Abstract klasses are filtered out unconditionally.69* If a klass is not yet initialized, i.e yet to run its <clinit>70* it is also filtered out so we don't accidentally71* trigger initialization.72*/73static bool is_allowed(const Klass* k) {74assert(k != NULL, "invariant");75return !(k->is_abstract() || k->should_be_initialized());76}7778static void fill_klasses(GrowableArray<const void*>& event_subklasses, const InstanceKlass* event_klass, JavaThread* thread) {79assert(event_subklasses.length() == 0, "invariant");80assert(event_klass != NULL, "invariant");81DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread));8283for (ClassHierarchyIterator iter(const_cast<InstanceKlass*>(event_klass)); !iter.done(); iter.next()) {84Klass* subk = iter.klass();85if (is_allowed(subk)) {86event_subklasses.append(subk);87}88}89}9091static void transform_klasses_to_local_jni_handles(GrowableArray<const void*>& event_subklasses, JavaThread* thread) {92assert(event_subklasses.is_nonempty(), "invariant");93DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread));9495for (int i = 0; i < event_subklasses.length(); ++i) {96const InstanceKlass* k = static_cast<const InstanceKlass*>(event_subklasses.at(i));97assert(is_allowed(k), "invariant");98event_subklasses.at_put(i, JfrJavaSupport::local_jni_handle(k->java_mirror(), thread));99}100}101102jobject JdkJfrEvent::get_all_klasses(TRAPS) {103DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));104initialize(THREAD);105assert(empty_java_util_arraylist != NULL, "should have been setup already!");106static const char jdk_jfr_event_name[] = "jdk/internal/event/Event";107Symbol* const event_klass_name = SymbolTable::probe(jdk_jfr_event_name, sizeof jdk_jfr_event_name - 1);108109if (NULL == event_klass_name) {110// not loaded yet111return empty_java_util_arraylist;112}113114const Klass* const klass = SystemDictionary::resolve_or_null(event_klass_name, THREAD);115assert(klass != NULL, "invariant");116assert(klass->is_instance_klass(), "invariant");117assert(JdkJfrEvent::is(klass), "invariant");118119if (klass->subklass() == NULL) {120return empty_java_util_arraylist;121}122123ResourceMark rm(THREAD);124GrowableArray<const void*> event_subklasses(initial_array_size);125fill_klasses(event_subklasses, InstanceKlass::cast(klass), THREAD);126127if (event_subklasses.is_empty()) {128return empty_java_util_arraylist;129}130131transform_klasses_to_local_jni_handles(event_subklasses, THREAD);132133Handle h_array_list(THREAD, new_java_util_arraylist(THREAD));134assert(h_array_list.not_null(), "invariant");135136static const char add_method_name[] = "add";137static const char add_method_signature[] = "(Ljava/lang/Object;)Z";138const Klass* const array_list_klass = JfrJavaSupport::klass(empty_java_util_arraylist);139assert(array_list_klass != NULL, "invariant");140141const Symbol* const add_method_sym = SymbolTable::new_symbol(add_method_name);142assert(add_method_sym != NULL, "invariant");143144const Symbol* const add_method_sig_sym = SymbolTable::new_symbol(add_method_signature);145assert(add_method_signature != NULL, "invariant");146147JavaValue result(T_BOOLEAN);148for (int i = 0; i < event_subklasses.length(); ++i) {149const jclass clazz = (const jclass)event_subklasses.at(i);150assert(JdkJfrEvent::is_subklass(clazz), "invariant");151JfrJavaArguments args(&result, array_list_klass, add_method_sym, add_method_sig_sym);152args.set_receiver(h_array_list());153args.push_jobject(clazz);154JfrJavaSupport::call_virtual(&args, THREAD);155if (HAS_PENDING_EXCEPTION || JNI_FALSE == result.get_jboolean()) {156return empty_java_util_arraylist;157}158}159return JfrJavaSupport::local_jni_handle(h_array_list(), THREAD);160}161162bool JdkJfrEvent::is(const Klass* k) {163return JfrTraceId::is_jdk_jfr_event(k);164}165166bool JdkJfrEvent::is(const jclass jc) {167return JfrTraceId::is_jdk_jfr_event(jc);168}169170void JdkJfrEvent::tag_as(const Klass* k) {171JfrTraceId::tag_as_jdk_jfr_event(k);172}173174bool JdkJfrEvent::is_subklass(const Klass* k) {175return JfrTraceId::is_jdk_jfr_event_sub(k);176}177178bool JdkJfrEvent::is_subklass(const jclass jc) {179return JfrTraceId::is_jdk_jfr_event_sub(jc);180}181182void JdkJfrEvent::tag_as_subklass(const Klass* k) {183JfrTraceId::tag_as_jdk_jfr_event_sub(k);184}185186void JdkJfrEvent::tag_as_subklass(const jclass jc) {187JfrTraceId::tag_as_jdk_jfr_event_sub(jc);188}189190bool JdkJfrEvent::is_a(const Klass* k) {191return JfrTraceId::in_jdk_jfr_event_hierarchy(k);192}193194bool JdkJfrEvent::is_a(const jclass jc) {195return JfrTraceId::in_jdk_jfr_event_hierarchy(jc);196}197198bool JdkJfrEvent::is_host(const Klass* k) {199return JfrTraceId::is_event_host(k);200}201202bool JdkJfrEvent::is_host(const jclass jc) {203return JfrTraceId::is_event_host(jc);204}205206void JdkJfrEvent::tag_as_host(const Klass* k) {207JfrTraceId::tag_as_event_host(k);208}209210void JdkJfrEvent::tag_as_host(const jclass jc) {211JfrTraceId::tag_as_event_host(jc);212}213214bool JdkJfrEvent::is_visible(const Klass* k) {215return JfrTraceId::in_visible_set(k);216}217218bool JdkJfrEvent::is_visible(const jclass jc) {219return JfrTraceId::in_visible_set(jc);220}221222223