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