Path: blob/master/src/hotspot/share/jfr/support/jfrKlassUnloading.cpp
41149 views
/*1* Copyright (c) 2020, 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 "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"26#include "jfr/support/jfrKlassUnloading.hpp"27#include "jfr/utilities/jfrPredicate.hpp"28#include "jfr/utilities/jfrRelation.hpp"29#include "runtime/mutexLocker.hpp"3031static const int initial_array_size = 64;3233template <typename T>34static GrowableArray<T>* c_heap_allocate_array(int size = initial_array_size) {35return new (ResourceObj::C_HEAP, mtTracing) GrowableArray<T>(size, mtTracing);36}3738// Track the set of unloaded klasses during a chunk / epoch.39static GrowableArray<traceid>* _unload_set_epoch_0 = NULL;40static GrowableArray<traceid>* _unload_set_epoch_1 = NULL;4142static s8 event_klass_unloaded_count = 0;4344static GrowableArray<traceid>* unload_set_epoch_0() {45if (_unload_set_epoch_0 == NULL) {46_unload_set_epoch_0 = c_heap_allocate_array<traceid>(initial_array_size);47}48return _unload_set_epoch_0;49}5051static GrowableArray<traceid>* unload_set_epoch_1() {52if (_unload_set_epoch_1 == NULL) {53_unload_set_epoch_1 = c_heap_allocate_array<traceid>(initial_array_size);54}55return _unload_set_epoch_1;56}5758static GrowableArray<traceid>* get_unload_set(u1 epoch) {59return epoch == 0 ? unload_set_epoch_0() : unload_set_epoch_1();60}6162static GrowableArray<traceid>* get_unload_set() {63return get_unload_set(JfrTraceIdEpoch::current());64}6566static GrowableArray<traceid>* get_unload_set_previous_epoch() {67return get_unload_set(JfrTraceIdEpoch::previous());68}6970static void sort_set(GrowableArray<traceid>* set) {71assert(set != NULL, "invariant");72assert(set->is_nonempty(), "invariant");73set->sort(sort_traceid);74}7576static bool is_nonempty_set(u1 epoch) {77if (epoch == 0) {78return _unload_set_epoch_0 != NULL && _unload_set_epoch_0->is_nonempty();79}80return _unload_set_epoch_1 != NULL && _unload_set_epoch_1->is_nonempty();81}8283void JfrKlassUnloading::sort(bool previous_epoch) {84assert_locked_or_safepoint(ClassLoaderDataGraph_lock);85if (is_nonempty_set(JfrTraceIdEpoch::current())) {86sort_set(get_unload_set());87}88if (previous_epoch && is_nonempty_set(JfrTraceIdEpoch::previous())) {89sort_set(get_unload_set_previous_epoch());90}91}9293void JfrKlassUnloading::clear() {94assert_locked_or_safepoint(ClassLoaderDataGraph_lock);95if (is_nonempty_set(JfrTraceIdEpoch::previous())) {96get_unload_set_previous_epoch()->clear();97}98}99100static bool add_to_unloaded_klass_set(traceid klass_id, bool current_epoch) {101assert_locked_or_safepoint(ClassLoaderDataGraph_lock);102GrowableArray<traceid>* const unload_set = current_epoch ? get_unload_set() : get_unload_set_previous_epoch();103assert(unload_set != NULL, "invariant");104assert(unload_set->find(klass_id) == -1, "invariant");105unload_set->append(klass_id);106return true;107}108109bool JfrKlassUnloading::on_unload(const Klass* k) {110assert(k != NULL, "invariant");111assert_locked_or_safepoint(ClassLoaderDataGraph_lock);112if (IS_JDK_JFR_EVENT_SUBKLASS(k)) {113++event_klass_unloaded_count;114}115return USED_ANY_EPOCH(k) && add_to_unloaded_klass_set(JfrTraceId::load_raw(k), USED_THIS_EPOCH(k));116}117118bool JfrKlassUnloading::is_unloaded(traceid klass_id, bool previous_epoch /* false */) {119assert_locked_or_safepoint(ClassLoaderDataGraph_lock);120if (previous_epoch) {121if (JfrPredicate<traceid, compare_traceid>::test(get_unload_set_previous_epoch(), klass_id)) {122return true;123}124}125return JfrPredicate<traceid, compare_traceid>::test(get_unload_set(), klass_id);126}127128int64_t JfrKlassUnloading::event_class_count() {129return event_klass_unloaded_count;130}131132133