Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/back/classTrack.c
38765 views
/*1* Copyright (c) 2001, 2005, 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. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* This module tracks classes that have been prepared, so as to27* be able to report which have been unloaded. On VM start-up28* and whenever new classes are loaded, all prepared classes'29* signatures are attached as JVMTI tag to the class object.30* Class unloading is tracked by registering31* ObjectFree callback on class objects. When this happens, we find32* the signature of the unloaded class(es) and report them back33* to the event handler to synthesize class-unload-events.34*/3536#include "util.h"37#include "bag.h"38#include "classTrack.h"3940#define NOT_TAGGED 04142/*43* The JVMTI tracking env to keep track of klass tags for class-unloads44*/45static jvmtiEnv* trackingEnv;4647/*48* A bag containing all the deleted classes' signatures. Must be accessed under49* classTrackLock.50*/51struct bag* deletedSignatures;5253/*54* Lock to keep integrity of deletedSignatures.55*/56static jrawMonitorID classTrackLock;5758/*59* Invoke the callback when classes are freed, find and record the signature60* in deletedSignatures. Those are only used in addPreparedClass() by the61* same thread.62*/63static void JNICALL64cbTrackingObjectFree(jvmtiEnv* jvmti_env, jlong tag)65{66debugMonitorEnter(classTrackLock);67if (deletedSignatures == NULL) {68debugMonitorExit(classTrackLock);69return;70}71*(char**)bagAdd(deletedSignatures) = (char*)jlong_to_ptr(tag);7273debugMonitorExit(classTrackLock);74}7576/*77* Called after class unloads have occurred.78* The signatures of classes which were unloaded are returned.79*/80struct bag *81classTrack_processUnloads(JNIEnv *env)82{83struct bag* deleted;84debugMonitorEnter(classTrackLock);85if (deletedSignatures == NULL) {86// Class tracking not initialized, nobody's interested.87debugMonitorExit(classTrackLock);88return NULL;89}90deleted = deletedSignatures;91deletedSignatures = bagCreateBag(sizeof(char*), 10);92debugMonitorExit(classTrackLock);93return deleted;94}9596/*97* Add a class to the prepared class table.98*/99void100classTrack_addPreparedClass(JNIEnv *env_unused, jclass klass)101{102jvmtiError error;103jvmtiEnv* env = trackingEnv;104char* signature;105106if (gdata && gdata->assertOn) {107// Check this is not already tagged.108jlong tag;109error = JVMTI_FUNC_PTR(trackingEnv, GetTag)(env, klass, &tag);110if (error != JVMTI_ERROR_NONE) {111EXIT_ERROR(error, "Unable to GetTag with class trackingEnv");112}113JDI_ASSERT(tag == NOT_TAGGED);114}115116error = classSignature(klass, &signature, NULL);117if (error != JVMTI_ERROR_NONE) {118EXIT_ERROR(error,"signature");119}120error = JVMTI_FUNC_PTR(trackingEnv, SetTag)(env, klass, ptr_to_jlong(signature));121if (error != JVMTI_ERROR_NONE) {122jvmtiDeallocate(signature);123EXIT_ERROR(error,"SetTag");124}125}126127static jboolean128setupEvents()129{130jvmtiError error;131jvmtiEventCallbacks cb;132jvmtiCapabilities caps;133memset(&caps, 0, sizeof(caps));134caps.can_generate_object_free_events = 1;135error = JVMTI_FUNC_PTR(trackingEnv, AddCapabilities)(trackingEnv, &caps);136if (error != JVMTI_ERROR_NONE) {137return JNI_FALSE;138}139memset(&cb, 0, sizeof(cb));140cb.ObjectFree = cbTrackingObjectFree;141error = JVMTI_FUNC_PTR(trackingEnv, SetEventCallbacks)(trackingEnv, &cb, sizeof(cb));142if (error != JVMTI_ERROR_NONE) {143return JNI_FALSE;144}145error = JVMTI_FUNC_PTR(trackingEnv, SetEventNotificationMode)(trackingEnv, JVMTI_ENABLE, JVMTI_EVENT_OBJECT_FREE, NULL);146if (error != JVMTI_ERROR_NONE) {147return JNI_FALSE;148}149return JNI_TRUE;150}151152/*153* Called once to initialize class-tracking.154*/155void156classTrack_initialize(JNIEnv *env)157{158jint classCount;159jclass *classes;160jvmtiError error;161jint i;162163deletedSignatures = NULL;164classTrackLock = debugMonitorCreate("Deleted class tag lock");165trackingEnv = getSpecialJvmti();166if (trackingEnv == NULL) {167EXIT_ERROR(AGENT_ERROR_INTERNAL, "Failed to allocate tag-tracking jvmtiEnv");168}169170171if (!setupEvents()) {172EXIT_ERROR(AGENT_ERROR_INTERNAL, "Unable to setup ObjectFree tracking");173}174175error = allLoadedClasses(&classes, &classCount);176if ( error == JVMTI_ERROR_NONE ) {177for (i = 0; i < classCount; i++) {178jclass klass = classes[i];179jint status;180jint wanted = JVMTI_CLASS_STATUS_PREPARED | JVMTI_CLASS_STATUS_ARRAY;181status = classStatus(klass);182if ((status & wanted) != 0) {183classTrack_addPreparedClass(env, klass);184}185}186jvmtiDeallocate(classes);187} else {188EXIT_ERROR(error,"loaded classes array");189}190}191192/*193* Called to activate class-tracking when a listener registers for EI_GC_FINISH.194*/195void196classTrack_activate(JNIEnv *env)197{198debugMonitorEnter(classTrackLock);199deletedSignatures = bagCreateBag(sizeof(char*), 1000);200debugMonitorExit(classTrackLock);201}202203static jboolean204cleanDeleted(void *signatureVoid, void *arg)205{206char* sig = *(char**)signatureVoid;207jvmtiDeallocate(sig);208return JNI_TRUE;209}210211/*212* Called when agent detaches.213*/214void215classTrack_reset(void)216{217debugMonitorEnter(classTrackLock);218219if (deletedSignatures != NULL) {220bagEnumerateOver(deletedSignatures, cleanDeleted, NULL);221bagDestroyBag(deletedSignatures);222deletedSignatures = NULL;223}224225debugMonitorExit(classTrackLock);226}227228229