xref: /aosp_15_r20/external/oj-libjdwp/src/share/back/classTrack.c (revision e82f7db8c62aed3c168547abe4f9f4aeceaebfc7)
1*e82f7db8SAndroid Build Coastguard Worker /*
2*e82f7db8SAndroid Build Coastguard Worker  * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
3*e82f7db8SAndroid Build Coastguard Worker  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*e82f7db8SAndroid Build Coastguard Worker  *
5*e82f7db8SAndroid Build Coastguard Worker  * This code is free software; you can redistribute it and/or modify it
6*e82f7db8SAndroid Build Coastguard Worker  * under the terms of the GNU General Public License version 2 only, as
7*e82f7db8SAndroid Build Coastguard Worker  * published by the Free Software Foundation.  Oracle designates this
8*e82f7db8SAndroid Build Coastguard Worker  * particular file as subject to the "Classpath" exception as provided
9*e82f7db8SAndroid Build Coastguard Worker  * by Oracle in the LICENSE file that accompanied this code.
10*e82f7db8SAndroid Build Coastguard Worker  *
11*e82f7db8SAndroid Build Coastguard Worker  * This code is distributed in the hope that it will be useful, but WITHOUT
12*e82f7db8SAndroid Build Coastguard Worker  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*e82f7db8SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14*e82f7db8SAndroid Build Coastguard Worker  * version 2 for more details (a copy is included in the LICENSE file that
15*e82f7db8SAndroid Build Coastguard Worker  * accompanied this code).
16*e82f7db8SAndroid Build Coastguard Worker  *
17*e82f7db8SAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License version
18*e82f7db8SAndroid Build Coastguard Worker  * 2 along with this work; if not, write to the Free Software Foundation,
19*e82f7db8SAndroid Build Coastguard Worker  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20*e82f7db8SAndroid Build Coastguard Worker  *
21*e82f7db8SAndroid Build Coastguard Worker  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22*e82f7db8SAndroid Build Coastguard Worker  * or visit www.oracle.com if you need additional information or have any
23*e82f7db8SAndroid Build Coastguard Worker  * questions.
24*e82f7db8SAndroid Build Coastguard Worker  */
25*e82f7db8SAndroid Build Coastguard Worker /*
26*e82f7db8SAndroid Build Coastguard Worker  * This module tracks classes that have been prepared, so as to
27*e82f7db8SAndroid Build Coastguard Worker  * be able to compute which have been unloaded.  On VM start-up
28*e82f7db8SAndroid Build Coastguard Worker  * all prepared classes are put in a table.  As class prepare
29*e82f7db8SAndroid Build Coastguard Worker  * events come in they are added to the table.  After an unload
30*e82f7db8SAndroid Build Coastguard Worker  * event or series of them, the VM can be asked for the list
31*e82f7db8SAndroid Build Coastguard Worker  * of classes; this list is compared against the table keep by
32*e82f7db8SAndroid Build Coastguard Worker  * this module, any classes no longer present are known to
33*e82f7db8SAndroid Build Coastguard Worker  * have been unloaded.
34*e82f7db8SAndroid Build Coastguard Worker  *
35*e82f7db8SAndroid Build Coastguard Worker  * ANDROID-CHANGED: This module is almost totally re-written
36*e82f7db8SAndroid Build Coastguard Worker  * for android. On android, we have a limited number of jweak
37*e82f7db8SAndroid Build Coastguard Worker  * references that can be around at any one time. In order to
38*e82f7db8SAndroid Build Coastguard Worker  * preserve this limited resource for user-code use we keep
39*e82f7db8SAndroid Build Coastguard Worker  * track of the status of classes using JVMTI tags.
40*e82f7db8SAndroid Build Coastguard Worker  *
41*e82f7db8SAndroid Build Coastguard Worker  * We keep a linked-list of the signatures of loaded classes
42*e82f7db8SAndroid Build Coastguard Worker  * associated with the tag we gave to that class. The tag is
43*e82f7db8SAndroid Build Coastguard Worker  * simply incremented every time we add a new class.
44*e82f7db8SAndroid Build Coastguard Worker  *
45*e82f7db8SAndroid Build Coastguard Worker  * We also request (on the separate tracking jvmtiEnv) an
46*e82f7db8SAndroid Build Coastguard Worker  * ObjectFree event be called for each of these classes. This
47*e82f7db8SAndroid Build Coastguard Worker  * allows us to keep a running list of all the classes known to
48*e82f7db8SAndroid Build Coastguard Worker  * have been collected since the last call to
49*e82f7db8SAndroid Build Coastguard Worker  * classTrack_processUnloads. On each call to processUnloads we
50*e82f7db8SAndroid Build Coastguard Worker  * iterate through this list and remove from the main list all
51*e82f7db8SAndroid Build Coastguard Worker  * the objects that have been collected. We then return a list of
52*e82f7db8SAndroid Build Coastguard Worker  * the class-signatures that have been collected.
53*e82f7db8SAndroid Build Coastguard Worker  *
54*e82f7db8SAndroid Build Coastguard Worker  * For efficiency and simplicity we don't bother retagging or
55*e82f7db8SAndroid Build Coastguard Worker  * re-using old tags, instead relying on the fact that no
56*e82f7db8SAndroid Build Coastguard Worker  * program will ever be able to exhaust the (2^64 - 1) possible
57*e82f7db8SAndroid Build Coastguard Worker  * tag values (which would require that many class-loads).
58*e82f7db8SAndroid Build Coastguard Worker  *
59*e82f7db8SAndroid Build Coastguard Worker  * This relies on the tagging and ObjectFree implementation being
60*e82f7db8SAndroid Build Coastguard Worker  * relatively efficient for performance. It has the advantage of
61*e82f7db8SAndroid Build Coastguard Worker  * not requiring any jweaks.
62*e82f7db8SAndroid Build Coastguard Worker  *
63*e82f7db8SAndroid Build Coastguard Worker  * All calls into any function of this module must be either
64*e82f7db8SAndroid Build Coastguard Worker  * done before the event-handler system is setup or done while
65*e82f7db8SAndroid Build Coastguard Worker  * holding the event handlerLock. The list of freed classes is
66*e82f7db8SAndroid Build Coastguard Worker  * protected by the classTagLock.
67*e82f7db8SAndroid Build Coastguard Worker  */
68*e82f7db8SAndroid Build Coastguard Worker 
69*e82f7db8SAndroid Build Coastguard Worker #include "util.h"
70*e82f7db8SAndroid Build Coastguard Worker #include "bag.h"
71*e82f7db8SAndroid Build Coastguard Worker #include "classTrack.h"
72*e82f7db8SAndroid Build Coastguard Worker 
73*e82f7db8SAndroid Build Coastguard Worker typedef struct KlassNode {
74*e82f7db8SAndroid Build Coastguard Worker     jlong klass_tag;         /* Tag the klass has in the tracking-env */
75*e82f7db8SAndroid Build Coastguard Worker     char *signature;         /* class signature */
76*e82f7db8SAndroid Build Coastguard Worker     struct KlassNode *next;  /* next node in this slot */
77*e82f7db8SAndroid Build Coastguard Worker } KlassNode;
78*e82f7db8SAndroid Build Coastguard Worker 
79*e82f7db8SAndroid Build Coastguard Worker /*
80*e82f7db8SAndroid Build Coastguard Worker  * pointer to first node of a linked list of prepared classes KlassNodes.
81*e82f7db8SAndroid Build Coastguard Worker  */
82*e82f7db8SAndroid Build Coastguard Worker static KlassNode *list;
83*e82f7db8SAndroid Build Coastguard Worker 
84*e82f7db8SAndroid Build Coastguard Worker /*
85*e82f7db8SAndroid Build Coastguard Worker  * The JVMTI env we use to keep track of klass tags which allows us to detect class-unloads.
86*e82f7db8SAndroid Build Coastguard Worker  */
87*e82f7db8SAndroid Build Coastguard Worker static jvmtiEnv *trackingEnv;
88*e82f7db8SAndroid Build Coastguard Worker 
89*e82f7db8SAndroid Build Coastguard Worker /*
90*e82f7db8SAndroid Build Coastguard Worker  * The current highest tag number in use by the trackingEnv.
91*e82f7db8SAndroid Build Coastguard Worker  *
92*e82f7db8SAndroid Build Coastguard Worker  * No need for synchronization since everything is done under the handlerLock.
93*e82f7db8SAndroid Build Coastguard Worker  */
94*e82f7db8SAndroid Build Coastguard Worker static jlong currentKlassTag;
95*e82f7db8SAndroid Build Coastguard Worker 
96*e82f7db8SAndroid Build Coastguard Worker /*
97*e82f7db8SAndroid Build Coastguard Worker  * A lock to protect access to 'deletedTagBag'
98*e82f7db8SAndroid Build Coastguard Worker  */
99*e82f7db8SAndroid Build Coastguard Worker static jrawMonitorID deletedTagLock;
100*e82f7db8SAndroid Build Coastguard Worker 
101*e82f7db8SAndroid Build Coastguard Worker /*
102*e82f7db8SAndroid Build Coastguard Worker  * A bag containing all the deleted klass_tags ids. This must be accessed under the
103*e82f7db8SAndroid Build Coastguard Worker  * deletedTagLock.
104*e82f7db8SAndroid Build Coastguard Worker  *
105*e82f7db8SAndroid Build Coastguard Worker  * It is cleared each time classTrack_processUnloads is called.
106*e82f7db8SAndroid Build Coastguard Worker  */
107*e82f7db8SAndroid Build Coastguard Worker struct bag* deletedTagBag;
108*e82f7db8SAndroid Build Coastguard Worker 
109*e82f7db8SAndroid Build Coastguard Worker /*
110*e82f7db8SAndroid Build Coastguard Worker  * The callback for when classes are freed. Only classes are called because this is registered with
111*e82f7db8SAndroid Build Coastguard Worker  * the trackingEnv which only tags classes.
112*e82f7db8SAndroid Build Coastguard Worker  */
113*e82f7db8SAndroid Build Coastguard Worker static void JNICALL
cbTrackingObjectFree(jvmtiEnv * jvmti_env,jlong tag)114*e82f7db8SAndroid Build Coastguard Worker cbTrackingObjectFree(jvmtiEnv* jvmti_env, jlong tag)
115*e82f7db8SAndroid Build Coastguard Worker {
116*e82f7db8SAndroid Build Coastguard Worker     debugMonitorEnterNoSuspend(deletedTagLock);
117*e82f7db8SAndroid Build Coastguard Worker     *(jlong*)bagAdd(deletedTagBag) = tag;
118*e82f7db8SAndroid Build Coastguard Worker     debugMonitorExit(deletedTagLock);
119*e82f7db8SAndroid Build Coastguard Worker }
120*e82f7db8SAndroid Build Coastguard Worker 
121*e82f7db8SAndroid Build Coastguard Worker /*
122*e82f7db8SAndroid Build Coastguard Worker  * Returns true (thus continuing the iteration) if the item is not the searched for tag.
123*e82f7db8SAndroid Build Coastguard Worker  */
124*e82f7db8SAndroid Build Coastguard Worker static jboolean
isNotTag(void * item,void * needle)125*e82f7db8SAndroid Build Coastguard Worker isNotTag(void* item, void* needle)
126*e82f7db8SAndroid Build Coastguard Worker {
127*e82f7db8SAndroid Build Coastguard Worker     return *(jlong*)item != *(jlong*)needle;
128*e82f7db8SAndroid Build Coastguard Worker }
129*e82f7db8SAndroid Build Coastguard Worker 
130*e82f7db8SAndroid Build Coastguard Worker /*
131*e82f7db8SAndroid Build Coastguard Worker  * This requires that deletedTagLock and the handlerLock are both held.
132*e82f7db8SAndroid Build Coastguard Worker  */
133*e82f7db8SAndroid Build Coastguard Worker static jboolean
isClassUnloaded(jlong tag)134*e82f7db8SAndroid Build Coastguard Worker isClassUnloaded(jlong tag)
135*e82f7db8SAndroid Build Coastguard Worker {
136*e82f7db8SAndroid Build Coastguard Worker     /* bagEnumerateOver returns true if 'func' returns true on all items and aborts early if not. */
137*e82f7db8SAndroid Build Coastguard Worker     return !bagEnumerateOver(deletedTagBag, isNotTag, &tag);
138*e82f7db8SAndroid Build Coastguard Worker }
139*e82f7db8SAndroid Build Coastguard Worker 
140*e82f7db8SAndroid Build Coastguard Worker /*
141*e82f7db8SAndroid Build Coastguard Worker  * Called after class unloads have occurred.  Creates a new hash table
142*e82f7db8SAndroid Build Coastguard Worker  * of currently loaded prepared classes.
143*e82f7db8SAndroid Build Coastguard Worker  * The signatures of classes which were unloaded (not present in the
144*e82f7db8SAndroid Build Coastguard Worker  * new table) are returned.
145*e82f7db8SAndroid Build Coastguard Worker  *
146*e82f7db8SAndroid Build Coastguard Worker  * NB This relies on addPreparedClass being called for every class loaded after the
147*e82f7db8SAndroid Build Coastguard Worker  * classTrack_initialize function is called. We will not request all loaded classes again after
148*e82f7db8SAndroid Build Coastguard Worker  * that. It also relies on not being called concurrently with any classTrack_addPreparedClass or
149*e82f7db8SAndroid Build Coastguard Worker  * other classTrack_processUnloads calls.
150*e82f7db8SAndroid Build Coastguard Worker  */
151*e82f7db8SAndroid Build Coastguard Worker struct bag *
classTrack_processUnloads(JNIEnv * env)152*e82f7db8SAndroid Build Coastguard Worker classTrack_processUnloads(JNIEnv *env)
153*e82f7db8SAndroid Build Coastguard Worker {
154*e82f7db8SAndroid Build Coastguard Worker     /* We could optimize this somewhat by holding the deletedTagLock for a much shorter time,
155*e82f7db8SAndroid Build Coastguard Worker      * replacing it as soon as we enter and then destroying it once we are done with it. This will
156*e82f7db8SAndroid Build Coastguard Worker      * cause a lot of memory churn and this function is not expected to be called that often.
157*e82f7db8SAndroid Build Coastguard Worker      * Furthermore due to the check for an empty bag (which should be very common) normally this
158*e82f7db8SAndroid Build Coastguard Worker      * will finish very quickly. In cases where there is a concurrent GC occuring and a class is
159*e82f7db8SAndroid Build Coastguard Worker      * being collected the GC-ing threads could be blocked until we are done but this is expected to
160*e82f7db8SAndroid Build Coastguard Worker      * be very rare.
161*e82f7db8SAndroid Build Coastguard Worker      */
162*e82f7db8SAndroid Build Coastguard Worker     debugMonitorEnter(deletedTagLock);
163*e82f7db8SAndroid Build Coastguard Worker     /* Take and return the deletedTagBag */
164*e82f7db8SAndroid Build Coastguard Worker     struct bag* deleted = bagCreateBag(sizeof(char*), bagSize(deletedTagBag));
165*e82f7db8SAndroid Build Coastguard Worker     /* The deletedTagBag is going to be much shorter than the klassNode list so we should walk the
166*e82f7db8SAndroid Build Coastguard Worker      * KlassNode list once and scan the deletedTagBag each time. We only need to this in the rare
167*e82f7db8SAndroid Build Coastguard Worker      * case that there was anything deleted though.
168*e82f7db8SAndroid Build Coastguard Worker      */
169*e82f7db8SAndroid Build Coastguard Worker     if (bagSize(deletedTagBag) != 0) {
170*e82f7db8SAndroid Build Coastguard Worker         KlassNode* node = list;
171*e82f7db8SAndroid Build Coastguard Worker         KlassNode** previousNext = &list;
172*e82f7db8SAndroid Build Coastguard Worker 
173*e82f7db8SAndroid Build Coastguard Worker         while (node != NULL) {
174*e82f7db8SAndroid Build Coastguard Worker             if (isClassUnloaded(node->klass_tag)) {
175*e82f7db8SAndroid Build Coastguard Worker                 /* Update the previous node's next pointer to point after this node. Note that we
176*e82f7db8SAndroid Build Coastguard Worker                  * update the value pointed to by previousNext but not the value of previousNext
177*e82f7db8SAndroid Build Coastguard Worker                  * itself.
178*e82f7db8SAndroid Build Coastguard Worker                  */
179*e82f7db8SAndroid Build Coastguard Worker                 *previousNext = node->next;
180*e82f7db8SAndroid Build Coastguard Worker                 /* Put this nodes signature into the deleted bag */
181*e82f7db8SAndroid Build Coastguard Worker                 *(char**)bagAdd(deleted) = node->signature;
182*e82f7db8SAndroid Build Coastguard Worker                 /* Deallocate the node */
183*e82f7db8SAndroid Build Coastguard Worker                 jvmtiDeallocate(node);
184*e82f7db8SAndroid Build Coastguard Worker             } else {
185*e82f7db8SAndroid Build Coastguard Worker                 /* This node will become the previous node so update the previousNext pointer to
186*e82f7db8SAndroid Build Coastguard Worker                  * this nodes next pointer.
187*e82f7db8SAndroid Build Coastguard Worker                  */
188*e82f7db8SAndroid Build Coastguard Worker                 previousNext = &(node->next);
189*e82f7db8SAndroid Build Coastguard Worker             }
190*e82f7db8SAndroid Build Coastguard Worker             node = *previousNext;
191*e82f7db8SAndroid Build Coastguard Worker         }
192*e82f7db8SAndroid Build Coastguard Worker         bagDeleteAll(deletedTagBag);
193*e82f7db8SAndroid Build Coastguard Worker     }
194*e82f7db8SAndroid Build Coastguard Worker     debugMonitorExit(deletedTagLock);
195*e82f7db8SAndroid Build Coastguard Worker     return deleted;
196*e82f7db8SAndroid Build Coastguard Worker }
197*e82f7db8SAndroid Build Coastguard Worker 
198*e82f7db8SAndroid Build Coastguard Worker /*
199*e82f7db8SAndroid Build Coastguard Worker  * Add a class to the prepared class list.
200*e82f7db8SAndroid Build Coastguard Worker  * Assumes no duplicates.
201*e82f7db8SAndroid Build Coastguard Worker  */
202*e82f7db8SAndroid Build Coastguard Worker void
classTrack_addPreparedClass(JNIEnv * env,jclass klass)203*e82f7db8SAndroid Build Coastguard Worker classTrack_addPreparedClass(JNIEnv *env, jclass klass)
204*e82f7db8SAndroid Build Coastguard Worker {
205*e82f7db8SAndroid Build Coastguard Worker     KlassNode *node;
206*e82f7db8SAndroid Build Coastguard Worker     jvmtiError error;
207*e82f7db8SAndroid Build Coastguard Worker 
208*e82f7db8SAndroid Build Coastguard Worker     if (gdata->assertOn) {
209*e82f7db8SAndroid Build Coastguard Worker         /* Check this is not a duplicate */
210*e82f7db8SAndroid Build Coastguard Worker         jlong tag;
211*e82f7db8SAndroid Build Coastguard Worker         error = JVMTI_FUNC_PTR(trackingEnv,GetTag)(trackingEnv, klass, &tag);
212*e82f7db8SAndroid Build Coastguard Worker         if (error != JVMTI_ERROR_NONE) {
213*e82f7db8SAndroid Build Coastguard Worker             EXIT_ERROR(error,"unable to get-tag with class trackingEnv!");
214*e82f7db8SAndroid Build Coastguard Worker         }
215*e82f7db8SAndroid Build Coastguard Worker         if (tag != 0l) {
216*e82f7db8SAndroid Build Coastguard Worker             JDI_ASSERT_FAILED("Attempting to insert duplicate class");
217*e82f7db8SAndroid Build Coastguard Worker         }
218*e82f7db8SAndroid Build Coastguard Worker     }
219*e82f7db8SAndroid Build Coastguard Worker 
220*e82f7db8SAndroid Build Coastguard Worker     node = jvmtiAllocate(sizeof(KlassNode));
221*e82f7db8SAndroid Build Coastguard Worker     if (node == NULL) {
222*e82f7db8SAndroid Build Coastguard Worker         EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"KlassNode");
223*e82f7db8SAndroid Build Coastguard Worker     }
224*e82f7db8SAndroid Build Coastguard Worker     error = classSignature(klass, &(node->signature), NULL);
225*e82f7db8SAndroid Build Coastguard Worker     if (error != JVMTI_ERROR_NONE) {
226*e82f7db8SAndroid Build Coastguard Worker         jvmtiDeallocate(node);
227*e82f7db8SAndroid Build Coastguard Worker         EXIT_ERROR(error,"signature");
228*e82f7db8SAndroid Build Coastguard Worker     }
229*e82f7db8SAndroid Build Coastguard Worker     node->klass_tag = ++currentKlassTag;
230*e82f7db8SAndroid Build Coastguard Worker     error = JVMTI_FUNC_PTR(trackingEnv,SetTag)(trackingEnv, klass, node->klass_tag);
231*e82f7db8SAndroid Build Coastguard Worker     if (error != JVMTI_ERROR_NONE) {
232*e82f7db8SAndroid Build Coastguard Worker         jvmtiDeallocate(node->signature);
233*e82f7db8SAndroid Build Coastguard Worker         jvmtiDeallocate(node);
234*e82f7db8SAndroid Build Coastguard Worker         EXIT_ERROR(error,"SetTag");
235*e82f7db8SAndroid Build Coastguard Worker     }
236*e82f7db8SAndroid Build Coastguard Worker 
237*e82f7db8SAndroid Build Coastguard Worker     /* Insert the new node */
238*e82f7db8SAndroid Build Coastguard Worker     node->next = list;
239*e82f7db8SAndroid Build Coastguard Worker     list = node;
240*e82f7db8SAndroid Build Coastguard Worker }
241*e82f7db8SAndroid Build Coastguard Worker 
242*e82f7db8SAndroid Build Coastguard Worker static jboolean
setupEvents()243*e82f7db8SAndroid Build Coastguard Worker setupEvents()
244*e82f7db8SAndroid Build Coastguard Worker {
245*e82f7db8SAndroid Build Coastguard Worker     jvmtiCapabilities caps;
246*e82f7db8SAndroid Build Coastguard Worker     memset(&caps, 0, sizeof(caps));
247*e82f7db8SAndroid Build Coastguard Worker     caps.can_generate_object_free_events = 1;
248*e82f7db8SAndroid Build Coastguard Worker     jvmtiError error = JVMTI_FUNC_PTR(trackingEnv,AddCapabilities)(trackingEnv, &caps);
249*e82f7db8SAndroid Build Coastguard Worker     if (error != JVMTI_ERROR_NONE) {
250*e82f7db8SAndroid Build Coastguard Worker         return JNI_FALSE;
251*e82f7db8SAndroid Build Coastguard Worker     }
252*e82f7db8SAndroid Build Coastguard Worker     jvmtiEventCallbacks cb;
253*e82f7db8SAndroid Build Coastguard Worker     memset(&cb, 0, sizeof(cb));
254*e82f7db8SAndroid Build Coastguard Worker     cb.ObjectFree = cbTrackingObjectFree;
255*e82f7db8SAndroid Build Coastguard Worker     error = JVMTI_FUNC_PTR(trackingEnv,SetEventCallbacks)(trackingEnv, &cb, sizeof(cb));
256*e82f7db8SAndroid Build Coastguard Worker     if (error != JVMTI_ERROR_NONE) {
257*e82f7db8SAndroid Build Coastguard Worker         return JNI_FALSE;
258*e82f7db8SAndroid Build Coastguard Worker     }
259*e82f7db8SAndroid Build Coastguard Worker     error = JVMTI_FUNC_PTR(trackingEnv,SetEventNotificationMode)
260*e82f7db8SAndroid Build Coastguard Worker             (trackingEnv, JVMTI_ENABLE, JVMTI_EVENT_OBJECT_FREE, NULL);
261*e82f7db8SAndroid Build Coastguard Worker     if (error != JVMTI_ERROR_NONE) {
262*e82f7db8SAndroid Build Coastguard Worker         return JNI_FALSE;
263*e82f7db8SAndroid Build Coastguard Worker     }
264*e82f7db8SAndroid Build Coastguard Worker     return JNI_TRUE;
265*e82f7db8SAndroid Build Coastguard Worker }
266*e82f7db8SAndroid Build Coastguard Worker 
267*e82f7db8SAndroid Build Coastguard Worker /*
268*e82f7db8SAndroid Build Coastguard Worker  * Called once to build the initial prepared class hash table.
269*e82f7db8SAndroid Build Coastguard Worker  */
270*e82f7db8SAndroid Build Coastguard Worker void
classTrack_initialize(JNIEnv * env)271*e82f7db8SAndroid Build Coastguard Worker classTrack_initialize(JNIEnv *env)
272*e82f7db8SAndroid Build Coastguard Worker {
273*e82f7db8SAndroid Build Coastguard Worker     /* ANDROID_CHANGED: Setup the tracking env and the currentKlassTag */
274*e82f7db8SAndroid Build Coastguard Worker     trackingEnv = getSpecialJvmti();
275*e82f7db8SAndroid Build Coastguard Worker     if ( trackingEnv == NULL ) {
276*e82f7db8SAndroid Build Coastguard Worker         EXIT_ERROR(AGENT_ERROR_INTERNAL,"Failed to allocate tag-tracking jvmtiEnv");
277*e82f7db8SAndroid Build Coastguard Worker     }
278*e82f7db8SAndroid Build Coastguard Worker     /* We want to create these before turning on the events or tagging anything. */
279*e82f7db8SAndroid Build Coastguard Worker     deletedTagLock = debugMonitorCreate("Deleted class tag lock");
280*e82f7db8SAndroid Build Coastguard Worker     deletedTagBag = bagCreateBag(sizeof(jlong), 10);
281*e82f7db8SAndroid Build Coastguard Worker     /* ANDROID-CHANGED: Setup the trackingEnv's ObjectFree event */
282*e82f7db8SAndroid Build Coastguard Worker     if (!setupEvents()) {
283*e82f7db8SAndroid Build Coastguard Worker         /* On android classes are usually not unloaded too often so this is not a huge loss. */
284*e82f7db8SAndroid Build Coastguard Worker         ERROR_MESSAGE(("Unable to setup class ObjectFree tracking! Class unloads will not "
285*e82f7db8SAndroid Build Coastguard Worker                        "be reported!"));
286*e82f7db8SAndroid Build Coastguard Worker     }
287*e82f7db8SAndroid Build Coastguard Worker     currentKlassTag = 0l;
288*e82f7db8SAndroid Build Coastguard Worker     list = NULL;
289*e82f7db8SAndroid Build Coastguard Worker     WITH_LOCAL_REFS(env, 1) {
290*e82f7db8SAndroid Build Coastguard Worker 
291*e82f7db8SAndroid Build Coastguard Worker         jint classCount;
292*e82f7db8SAndroid Build Coastguard Worker         jclass *classes;
293*e82f7db8SAndroid Build Coastguard Worker         jvmtiError error;
294*e82f7db8SAndroid Build Coastguard Worker         jint i;
295*e82f7db8SAndroid Build Coastguard Worker 
296*e82f7db8SAndroid Build Coastguard Worker         error = allLoadedClasses(&classes, &classCount);
297*e82f7db8SAndroid Build Coastguard Worker         if ( error == JVMTI_ERROR_NONE ) {
298*e82f7db8SAndroid Build Coastguard Worker             for (i=0; i<classCount; i++) {
299*e82f7db8SAndroid Build Coastguard Worker                 jclass klass = classes[i];
300*e82f7db8SAndroid Build Coastguard Worker                 jint status;
301*e82f7db8SAndroid Build Coastguard Worker                 jint wanted =
302*e82f7db8SAndroid Build Coastguard Worker                     (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY);
303*e82f7db8SAndroid Build Coastguard Worker 
304*e82f7db8SAndroid Build Coastguard Worker                 /* We only want prepared classes and arrays */
305*e82f7db8SAndroid Build Coastguard Worker                 status = classStatus(klass);
306*e82f7db8SAndroid Build Coastguard Worker                 if ( (status & wanted) != 0 ) {
307*e82f7db8SAndroid Build Coastguard Worker                     classTrack_addPreparedClass(env, klass);
308*e82f7db8SAndroid Build Coastguard Worker                 }
309*e82f7db8SAndroid Build Coastguard Worker             }
310*e82f7db8SAndroid Build Coastguard Worker             jvmtiDeallocate(classes);
311*e82f7db8SAndroid Build Coastguard Worker         } else {
312*e82f7db8SAndroid Build Coastguard Worker             EXIT_ERROR(error,"loaded classes array");
313*e82f7db8SAndroid Build Coastguard Worker         }
314*e82f7db8SAndroid Build Coastguard Worker 
315*e82f7db8SAndroid Build Coastguard Worker     } END_WITH_LOCAL_REFS(env)
316*e82f7db8SAndroid Build Coastguard Worker 
317*e82f7db8SAndroid Build Coastguard Worker }
318*e82f7db8SAndroid Build Coastguard Worker 
319*e82f7db8SAndroid Build Coastguard Worker void
classTrack_reset(void)320*e82f7db8SAndroid Build Coastguard Worker classTrack_reset(void)
321*e82f7db8SAndroid Build Coastguard Worker {
322*e82f7db8SAndroid Build Coastguard Worker }
323