jdk/src/share/demo/jvmti/heapTracker/heapTracker.c
author ohair
Wed, 06 Apr 2011 22:06:11 -0700
changeset 9035 1255eb81cc2f
parent 7798 be6c7160f8fc
child 10292 ed7db6a12c2a
permissions -rw-r--r--
7033660: Update copyright year to 2011 on any files changed in 2011 Reviewed-by: dholmes
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
9035
1255eb81cc2f 7033660: Update copyright year to 2011 on any files changed in 2011
ohair
parents: 7798
diff changeset
     2
 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 * Redistribution and use in source and binary forms, with or without
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * modification, are permitted provided that the following conditions
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * are met:
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 *   - Redistributions of source code must retain the above copyright
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 *     notice, this list of conditions and the following disclaimer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 *   - Redistributions in binary form must reproduce the above copyright
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 *     notice, this list of conditions and the following disclaimer in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 *     documentation and/or other materials provided with the distribution.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    15
 *   - Neither the name of Oracle nor the names of its
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *     contributors may be used to endorse or promote products derived
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 *     from this software without specific prior written permission.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
#include "stdlib.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
#include "heapTracker.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
#include "java_crw_demo.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
#include "jni.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
#include "jvmti.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
#include "agent_util.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
/* -------------------------------------------------------------------
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
 * Some constant names that tie to Java class/method names.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
 *    We assume the Java class whose static methods we will be calling
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
 *    looks like:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 * public class HeapTracker {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 *     private static int engaged;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 *     private static native void _newobj(Object thr, Object o);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 *     public static void newobj(Object o)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 *     {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 *              if ( engaged != 0 ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 *               _newobj(Thread.currentThread(), o);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 *           }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 *     }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 *     private static native void _newarr(Object thr, Object a);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 *     public static void newarr(Object a)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 *     {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 *            if ( engaged != 0 ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 *               _newarr(Thread.currentThread(), a);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 *           }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 *     }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 * }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 *    The engaged field allows us to inject all classes (even system classes)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 *    and delay the actual calls to the native code until the VM has reached
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 *    a safe time to call native methods (Past the JVMTI VM_START event).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
#define HEAP_TRACKER_class           HeapTracker /* Name of class we are using */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
#define HEAP_TRACKER_newobj        newobj   /* Name of java init method */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
#define HEAP_TRACKER_newarr        newarr   /* Name of java newarray method */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
#define HEAP_TRACKER_native_newobj _newobj  /* Name of java newobj native */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
#define HEAP_TRACKER_native_newarr _newarr  /* Name of java newarray native */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
#define HEAP_TRACKER_engaged       engaged  /* Name of static field switch */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
/* C macros to create strings from tokens */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
#define _STRING(s) #s
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
#define STRING(s) _STRING(s)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
/* ------------------------------------------------------------------- */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
/* Flavors of traces (to separate out stack traces) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
typedef enum {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    TRACE_FIRST                        = 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
    TRACE_USER                        = 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
    TRACE_BEFORE_VM_START        = 1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
    TRACE_BEFORE_VM_INIT        = 2,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
    TRACE_VM_OBJECT                = 3,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    TRACE_MYSTERY                = 4,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
    TRACE_LAST                        = 4
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
} TraceFlavor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
static char * flavorDesc[] = {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    "",
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
    "before VM_START",
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
    "before VM_INIT",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
    "VM_OBJECT",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    "unknown"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
};
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
/* Trace (Stack Trace) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
#define MAX_FRAMES 6
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
typedef struct Trace {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    /* Number of frames (includes HEAP_TRACKER methods) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
    jint           nframes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    /* Frames from GetStackTrace() (2 extra for HEAP_TRACKER methods) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
    jvmtiFrameInfo frames[MAX_FRAMES+2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
    /* Used to make some traces unique */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
    TraceFlavor    flavor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
} Trace;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
/* Trace information (more than one object will have this as a tag) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
typedef struct TraceInfo {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
    /* Trace where this object was allocated from */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
    Trace             trace;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
    /* 64 bit hash code that attempts to identify this specific trace */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
    jlong             hashCode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
    /* Total space taken up by objects allocated from this trace */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
    jlong             totalSpace;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
    /* Total count of objects ever allocated from this trace */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
    int               totalCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
    /* Total live objects that were allocated from this trace */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
    int               useCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    /* The next TraceInfo in the hash bucket chain */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
    struct TraceInfo *next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
} TraceInfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
/* Global agent data structure */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
typedef struct {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
    /* JVMTI Environment */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
    jvmtiEnv      *jvmti;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
    /* State of the VM flags */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
    jboolean       vmStarted;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
    jboolean       vmInitialized;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
    jboolean       vmDead;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
    /* Options */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
    int            maxDump;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
    /* Data access Lock */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
    jrawMonitorID  lock;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
    /* Counter on classes where BCI has been applied */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
    jint           ccount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
    /* Hash table to lookup TraceInfo's via Trace's */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
    #define HASH_INDEX_BIT_WIDTH 12 /* 4096 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
    #define HASH_BUCKET_COUNT (1<<HASH_INDEX_BIT_WIDTH)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
    #define HASH_INDEX_MASK (HASH_BUCKET_COUNT-1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
    TraceInfo     *hashBuckets[HASH_BUCKET_COUNT];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
    /* Count of TraceInfo's allocated */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
    int            traceInfoCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
    /* Pre-defined traces for the system and mystery situations */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
    TraceInfo     *emptyTrace[TRACE_LAST+1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
} GlobalAgentData;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
static GlobalAgentData *gdata;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
/* Enter a critical section by doing a JVMTI Raw Monitor Enter */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
enterCriticalSection(jvmtiEnv *jvmti)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
    error = (*jvmti)->RawMonitorEnter(jvmti, gdata->lock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
    check_jvmti_error(jvmti, error, "Cannot enter with raw monitor");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
/* Exit a critical section by doing a JVMTI Raw Monitor Exit */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
exitCriticalSection(jvmtiEnv *jvmti)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
    error = (*jvmti)->RawMonitorExit(jvmti, gdata->lock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
    check_jvmti_error(jvmti, error, "Cannot exit with raw monitor");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
/* Update stats on a TraceInfo */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
static TraceInfo *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
updateStats(TraceInfo *tinfo)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
    tinfo->totalCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
    tinfo->useCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
    return tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
/* Get TraceInfo for empty stack */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
static TraceInfo *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
emptyTrace(TraceFlavor flavor)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
    return updateStats(gdata->emptyTrace[flavor]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
/* Allocate new TraceInfo */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
static TraceInfo *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
newTraceInfo(Trace *trace, jlong hashCode, TraceFlavor flavor)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
    TraceInfo *tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
    tinfo = (TraceInfo*)calloc(1, sizeof(TraceInfo));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
    if ( tinfo == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
        fatal_error("ERROR: Ran out of malloc() space\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
        int hashIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
        tinfo->trace = *trace;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
        tinfo->trace.flavor = flavor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
        tinfo->hashCode = hashCode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
        gdata->traceInfoCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
        hashIndex = (int)(hashCode & HASH_INDEX_MASK);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
        tinfo->next = gdata->hashBuckets[hashIndex];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
        gdata->hashBuckets[hashIndex] = tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
    return tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
/* Create hash code for a Trace */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
static jlong
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
hashTrace(Trace *trace)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
    jlong hashCode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
    int   i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
    hashCode = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
    for ( i = 0 ; i < trace->nframes ; i++ ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
        hashCode = (hashCode << 3) +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
                (jlong)(ptrdiff_t)(void*)(trace->frames[i].method);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
        hashCode = (hashCode << 2) +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
                (jlong)(trace->frames[i].location);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
    hashCode = (hashCode << 3) + trace->nframes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
    hashCode += trace->flavor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
    return hashCode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
/* Lookup or create a new TraceInfo */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
static TraceInfo *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
lookupOrEnter(jvmtiEnv *jvmti, Trace *trace, TraceFlavor flavor)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
    TraceInfo *tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
    jlong      hashCode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
    /* Calculate hash code (outside critical section to lessen contention) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
    hashCode = hashTrace(trace);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
    /* Do a lookup in the hash table */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
    enterCriticalSection(jvmti); {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
        TraceInfo *prev;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
        int        hashIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
        /* Start with first item in hash buck chain */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
        prev = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
        hashIndex = (int)(hashCode & HASH_INDEX_MASK);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
        tinfo = gdata->hashBuckets[hashIndex];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
        while ( tinfo != NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
            if ( tinfo->hashCode == hashCode &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
                 memcmp(trace, &(tinfo->trace), sizeof(Trace))==0 ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
                 /* We found one that matches, move to head of bucket chain */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
                 if ( prev != NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
                     /* Remove from list and add to head of list */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
                     prev->next = tinfo->next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
                     tinfo->next = gdata->hashBuckets[hashIndex];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
                     gdata->hashBuckets[hashIndex] = tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
                 }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
                 /* Break out */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
                 break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
            prev = tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
            tinfo = tinfo->next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
        /* If we didn't find anything we need to enter a new entry */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
        if ( tinfo == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
            /* Create new hash table element */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
            tinfo = newTraceInfo(trace, hashCode, flavor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
        /* Update stats */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        (void)updateStats(tinfo);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
    } exitCriticalSection(jvmti);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
    return tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
/* Get TraceInfo for this allocation */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
static TraceInfo *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
findTraceInfo(jvmtiEnv *jvmti, jthread thread, TraceFlavor flavor)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
    TraceInfo *tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
    tinfo = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
    if ( thread != NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
        static Trace  empty;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
        Trace         trace;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
        /* Before VM_INIT thread could be NULL, watch out */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
        trace = empty;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
        error = (*jvmti)->GetStackTrace(jvmti, thread, 0, MAX_FRAMES+2,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
                            trace.frames, &(trace.nframes));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
        /* If we get a PHASE error, the VM isn't ready, or it died */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
        if ( error == JVMTI_ERROR_WRONG_PHASE ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
            /* It is assumed this is before VM_INIT */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
            if ( flavor == TRACE_USER ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
                tinfo = emptyTrace(TRACE_BEFORE_VM_INIT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
                tinfo = emptyTrace(flavor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
            check_jvmti_error(jvmti, error, "Cannot get stack trace");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
            /* Lookup this entry */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
            tinfo = lookupOrEnter(jvmti, &trace, flavor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
        /* If thread==NULL, it's assumed this is before VM_START */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
        if ( flavor == TRACE_USER ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
            tinfo = emptyTrace(TRACE_BEFORE_VM_START);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
            tinfo = emptyTrace(flavor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
    return tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
/* Tag an object with a TraceInfo pointer. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
tagObjectWithTraceInfo(jvmtiEnv *jvmti, jobject object, TraceInfo *tinfo)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
    jlong      tag;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
    /* Tag this object with this TraceInfo pointer */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
    tag = (jlong)(ptrdiff_t)(void*)tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
    error = (*jvmti)->SetTag(jvmti, object, tag);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
    check_jvmti_error(jvmti, error, "Cannot tag object");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
/* Java Native Method for Object.<init> */
7798
be6c7160f8fc 6927816: Demo crash in heaptracker with Non-Sun JDK due to possible violation of JNI spec
alanb
parents: 5506
diff changeset
   343
static void JNICALL
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
HEAP_TRACKER_native_newobj(JNIEnv *env, jclass klass, jthread thread, jobject o)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
    TraceInfo *tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
    if ( gdata->vmDead ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
    tinfo = findTraceInfo(gdata->jvmti, thread, TRACE_USER);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
    tagObjectWithTraceInfo(gdata->jvmti, o, tinfo);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
/* Java Native Method for newarray */
7798
be6c7160f8fc 6927816: Demo crash in heaptracker with Non-Sun JDK due to possible violation of JNI spec
alanb
parents: 5506
diff changeset
   356
static void JNICALL
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
HEAP_TRACKER_native_newarr(JNIEnv *env, jclass klass, jthread thread, jobject a)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
    TraceInfo *tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
    if ( gdata->vmDead ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
    tinfo = findTraceInfo(gdata->jvmti, thread, TRACE_USER);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
    tagObjectWithTraceInfo(gdata->jvmti, a, tinfo);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
/* Callback for JVMTI_EVENT_VM_START */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
static void JNICALL
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
cbVMStart(jvmtiEnv *jvmti, JNIEnv *env)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
    enterCriticalSection(jvmti); {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
        jclass klass;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
        jfieldID field;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
        jint rc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
        /* Java Native Methods for class */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
        static JNINativeMethod registry[2] = {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
            {STRING(HEAP_TRACKER_native_newobj), "(Ljava/lang/Object;Ljava/lang/Object;)V",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
                (void*)&HEAP_TRACKER_native_newobj},
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
            {STRING(HEAP_TRACKER_native_newarr), "(Ljava/lang/Object;Ljava/lang/Object;)V",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
                (void*)&HEAP_TRACKER_native_newarr}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
        };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
        /* Register Natives for class whose methods we use */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
        klass = (*env)->FindClass(env, STRING(HEAP_TRACKER_class));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
        if ( klass == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
            fatal_error("ERROR: JNI: Cannot find %s with FindClass\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
                        STRING(HEAP_TRACKER_class));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
        rc = (*env)->RegisterNatives(env, klass, registry, 2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
        if ( rc != 0 ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
            fatal_error("ERROR: JNI: Cannot register natives for class %s\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
                        STRING(HEAP_TRACKER_class));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
        /* Engage calls. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
        field = (*env)->GetStaticFieldID(env, klass, STRING(HEAP_TRACKER_engaged), "I");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
        if ( field == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
            fatal_error("ERROR: JNI: Cannot get field from %s\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
                        STRING(HEAP_TRACKER_class));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
        (*env)->SetStaticIntField(env, klass, field, 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
        /* Indicate VM has started */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
        gdata->vmStarted = JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
    } exitCriticalSection(jvmti);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
/* Iterate Through Heap callback */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
static jint JNICALL
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
cbObjectTagger(jlong class_tag, jlong size, jlong* tag_ptr, jint length,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
               void *user_data)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
    TraceInfo *tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
    tinfo = emptyTrace(TRACE_BEFORE_VM_INIT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
    *tag_ptr = (jlong)(ptrdiff_t)(void*)tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
    return JVMTI_VISIT_OBJECTS;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
/* Callback for JVMTI_EVENT_VM_INIT */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
static void JNICALL
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
cbVMInit(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
    jvmtiHeapCallbacks heapCallbacks;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
    jvmtiError         error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
    /* Iterate through heap, find all untagged objects allocated before this */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
    (void)memset(&heapCallbacks, 0, sizeof(heapCallbacks));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
    heapCallbacks.heap_iteration_callback = &cbObjectTagger;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
    error = (*jvmti)->IterateThroughHeap(jvmti, JVMTI_HEAP_FILTER_TAGGED,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
                                         NULL, &heapCallbacks, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
    check_jvmti_error(jvmti, error, "Cannot iterate through heap");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
    enterCriticalSection(jvmti); {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
        /* Indicate VM is initialized */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
        gdata->vmInitialized = JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
    } exitCriticalSection(jvmti);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
/* Iterate Through Heap callback */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
static jint JNICALL
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
cbObjectSpaceCounter(jlong class_tag, jlong size, jlong* tag_ptr, jint length,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
                     void *user_data)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
    TraceInfo *tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
    tinfo = (TraceInfo*)(ptrdiff_t)(*tag_ptr);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
    if ( tinfo == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
        tinfo = emptyTrace(TRACE_MYSTERY);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
        *tag_ptr = (jlong)(ptrdiff_t)(void*)tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
    tinfo->totalSpace += size;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
    return JVMTI_VISIT_OBJECTS;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
/* Qsort compare function */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
static int
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
compareInfo(const void *p1, const void *p2)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
    TraceInfo *tinfo1, *tinfo2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
    tinfo1 = *((TraceInfo**)p1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
    tinfo2 = *((TraceInfo**)p2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
    return (int)(tinfo2->totalSpace - tinfo1->totalSpace);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
/* Frame to text */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
frameToString(jvmtiEnv *jvmti, char *buf, int buflen, jvmtiFrameInfo *finfo)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
    jvmtiError           error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
    jclass               klass;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
    char                *signature;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
    char                *methodname;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
    char                *methodsig;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
    jboolean             isNative;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
    char                *filename;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
    int                  lineCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
    jvmtiLineNumberEntry*lineTable;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
    int                  lineNumber;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
    /* Initialize defaults */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
    buf[0]     = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
    klass      = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
    signature  = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
    methodname = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
    methodsig  = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
    isNative   = JNI_FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
    filename   = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
    lineCount  = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
    lineTable  = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
    lineNumber = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
    /* Get jclass object for the jmethodID */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
    error = (*jvmti)->GetMethodDeclaringClass(jvmti, finfo->method, &klass);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
    check_jvmti_error(jvmti, error, "Cannot get method's class");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
    /* Get the class signature */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
    error = (*jvmti)->GetClassSignature(jvmti, klass, &signature, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
    check_jvmti_error(jvmti, error, "Cannot get class signature");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
    /* Skip all this if it's our own Tracker method */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
    if ( strcmp(signature, "L" STRING(HEAP_TRACKER_class) ";" ) == 0 ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
        deallocate(jvmti, signature);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
    /* Get the name and signature for the method */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
    error = (*jvmti)->GetMethodName(jvmti, finfo->method,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
                &methodname, &methodsig, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
    check_jvmti_error(jvmti, error, "Cannot method name");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
    /* Check to see if it's a native method, which means no lineNumber */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
    error = (*jvmti)->IsMethodNative(jvmti, finfo->method, &isNative);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
    check_jvmti_error(jvmti, error, "Cannot get method native status");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
    /* Get source file name */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
    error = (*jvmti)->GetSourceFileName(jvmti, klass, &filename);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
    if ( error != JVMTI_ERROR_NONE && error != JVMTI_ERROR_ABSENT_INFORMATION ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
        check_jvmti_error(jvmti, error, "Cannot get source filename");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
    /* Get lineNumber if we can */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
    if ( !isNative ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
        int i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
        /* Get method line table */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
        error = (*jvmti)->GetLineNumberTable(jvmti, finfo->method, &lineCount, &lineTable);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
        if ( error == JVMTI_ERROR_NONE ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
            /* Search for line */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
            lineNumber = lineTable[0].line_number;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
            for ( i = 1 ; i < lineCount ; i++ ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
                if ( finfo->location < lineTable[i].start_location ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
                lineNumber = lineTable[i].line_number;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
        } else if ( error != JVMTI_ERROR_ABSENT_INFORMATION ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
            check_jvmti_error(jvmti, error, "Cannot get method line table");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
    /* Create string for this frame location.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
     *    NOTE: These char* quantities are mUTF (Modified UTF-8) bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
     *          and should actually be converted to the default system
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
     *          character encoding. Sending them to things like
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
     *          printf() without converting them is actually an I18n
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
     *          (Internationalization) error.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
    (void)sprintf(buf, "%s.%s@%d[%s:%d]",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
            (signature==NULL?"UnknownClass":signature),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
            (methodname==NULL?"UnknownMethod":methodname),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
            (int)finfo->location,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
            (filename==NULL?"UnknownFile":filename),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
            lineNumber);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
    /* Free up JVMTI space allocated by the above calls */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
    deallocate(jvmti, signature);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
    deallocate(jvmti, methodname);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
    deallocate(jvmti, methodsig);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
    deallocate(jvmti, filename);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
    deallocate(jvmti, lineTable);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
/* Print the information */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
printTraceInfo(jvmtiEnv *jvmti, int index, TraceInfo* tinfo)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
    if ( tinfo == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
        fatal_error("%d: NULL ENTRY ERROR\n", index);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
    stdout_message("%2d: %7d bytes %5d objects %5d live %s",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
                index, (int)tinfo->totalSpace, tinfo->totalCount,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
                tinfo->useCount, flavorDesc[tinfo->trace.flavor]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
    if (  tinfo->trace.nframes > 0 ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
        int i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
        int fcount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
        fcount = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
        stdout_message(" stack=(");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
        for ( i = 0 ; i < tinfo->trace.nframes ; i++ ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
            char buf[4096];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
            frameToString(jvmti, buf, (int)sizeof(buf), tinfo->trace.frames+i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
            if ( buf[0] == 0 ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
                continue; /* Skip the ones that are from Tracker class */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
            fcount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
            stdout_message("%s", buf);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
            if ( i < (tinfo->trace.nframes-1) ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
                stdout_message(",");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
        stdout_message(") nframes=%d\n", fcount);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
        stdout_message(" stack=<empty>\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
/* Callback for JVMTI_EVENT_VM_DEATH */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
static void JNICALL
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
cbVMDeath(jvmtiEnv *jvmti, JNIEnv *env)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
    jvmtiHeapCallbacks heapCallbacks;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
    jvmtiError         error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
    /* These are purposely done outside the critical section */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
    /* Force garbage collection now so we get our ObjectFree calls */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
    error = (*jvmti)->ForceGarbageCollection(jvmti);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
    check_jvmti_error(jvmti, error, "Cannot force garbage collection");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
    /* Iterate through heap and find all objects */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
    (void)memset(&heapCallbacks, 0, sizeof(heapCallbacks));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
    heapCallbacks.heap_iteration_callback = &cbObjectSpaceCounter;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
    error = (*jvmti)->IterateThroughHeap(jvmti, 0, NULL, &heapCallbacks, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
    check_jvmti_error(jvmti, error, "Cannot iterate through heap");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
    /* Process VM Death */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
    enterCriticalSection(jvmti); {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
        jclass              klass;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
        jfieldID            field;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
        jvmtiEventCallbacks callbacks;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
        /* Disengage calls in HEAP_TRACKER_class. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
        klass = (*env)->FindClass(env, STRING(HEAP_TRACKER_class));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
        if ( klass == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
            fatal_error("ERROR: JNI: Cannot find %s with FindClass\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
                        STRING(HEAP_TRACKER_class));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
        field = (*env)->GetStaticFieldID(env, klass, STRING(HEAP_TRACKER_engaged), "I");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
        if ( field == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
            fatal_error("ERROR: JNI: Cannot get field from %s\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
                        STRING(HEAP_TRACKER_class));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
        (*env)->SetStaticIntField(env, klass, field, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
        /* The critical section here is important to hold back the VM death
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
         *    until all other callbacks have completed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
        /* Clear out all callbacks. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
        (void)memset(&callbacks,0, sizeof(callbacks));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
        error = (*jvmti)->SetEventCallbacks(jvmti, &callbacks,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
                                            (jint)sizeof(callbacks));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
        check_jvmti_error(jvmti, error, "Cannot set jvmti callbacks");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
        /* Since this critical section could be holding up other threads
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
         *   in other event callbacks, we need to indicate that the VM is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
         *   dead so that the other callbacks can short circuit their work.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
         *   We don't expect an further events after VmDeath but we do need
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
         *   to be careful that existing threads might be in our own agent
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
         *   callback code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
        gdata->vmDead = JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
        /* Dump all objects */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
        if ( gdata->traceInfoCount > 0 ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
            TraceInfo **list;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
            int         count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
            int         i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
            stdout_message("Dumping heap trace information\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
            /* Create single array of pointers to TraceInfo's, sort, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
             *   print top gdata->maxDump top space users.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
            list = (TraceInfo**)calloc(gdata->traceInfoCount,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
                                              sizeof(TraceInfo*));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
            if ( list == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
                fatal_error("ERROR: Ran out of malloc() space\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
            count = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
            for ( i = 0 ; i < HASH_BUCKET_COUNT ; i++ ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
                TraceInfo *tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
                tinfo = gdata->hashBuckets[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
                while ( tinfo != NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
                    if ( count < gdata->traceInfoCount ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
                        list[count++] = tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
                    tinfo = tinfo->next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
            if ( count != gdata->traceInfoCount ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
                fatal_error("ERROR: Count found by iterate doesn't match ours:"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
                        " count=%d != traceInfoCount==%d\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
                        count, gdata->traceInfoCount);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
            qsort(list, count, sizeof(TraceInfo*), &compareInfo);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
            for ( i = 0 ; i < count ; i++ ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
                if ( i >= gdata->maxDump ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
                printTraceInfo(jvmti, i+1, list[i]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
            (void)free(list);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
    } exitCriticalSection(jvmti);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
/* Callback for JVMTI_EVENT_VM_OBJECT_ALLOC */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
static void JNICALL
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
cbVMObjectAlloc(jvmtiEnv *jvmti, JNIEnv *env, jthread thread,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
                jobject object, jclass object_klass, jlong size)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
    TraceInfo *tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
    if ( gdata->vmDead ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
    tinfo = findTraceInfo(jvmti, thread, TRACE_VM_OBJECT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
    tagObjectWithTraceInfo(jvmti, object, tinfo);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
/* Callback for JVMTI_EVENT_OBJECT_FREE */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
static void JNICALL
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
cbObjectFree(jvmtiEnv *jvmti, jlong tag)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
    TraceInfo *tinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
    if ( gdata->vmDead ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
    /* The object tag is actually a pointer to a TraceInfo structure */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
    tinfo = (TraceInfo*)(void*)(ptrdiff_t)tag;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
    /* Decrement the use count */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
    tinfo->useCount--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
/* Callback for JVMTI_EVENT_CLASS_FILE_LOAD_HOOK */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
static void JNICALL
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
cbClassFileLoadHook(jvmtiEnv *jvmti, JNIEnv* env,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
                jclass class_being_redefined, jobject loader,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
                const char* name, jobject protection_domain,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
                jint class_data_len, const unsigned char* class_data,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
                jint* new_class_data_len, unsigned char** new_class_data)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
    enterCriticalSection(jvmti); {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
        /* It's possible we get here right after VmDeath event, be careful */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
        if ( !gdata->vmDead ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
            const char * classname;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
            /* Name can be NULL, make sure we avoid SEGV's */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
            if ( name == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
                classname = java_crw_demo_classname(class_data, class_data_len,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
                                NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
                if ( classname == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
                    fatal_error("ERROR: No classname in classfile\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
                classname = strdup(name);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
                if ( classname == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
                    fatal_error("ERROR: Ran out of malloc() space\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
            *new_class_data_len = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
            *new_class_data     = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
            /* The tracker class itself? */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
            if ( strcmp(classname, STRING(HEAP_TRACKER_class)) != 0 ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
                jint           cnum;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
                int            systemClass;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
                unsigned char *newImage;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
                long           newLength;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
                /* Get number for every class file image loaded */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
                cnum = gdata->ccount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
                /* Is it a system class? If the class load is before VmStart
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
                 *   then we will consider it a system class that should
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
                 *   be treated carefully. (See java_crw_demo)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
                systemClass = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
                if ( !gdata->vmStarted ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
                    systemClass = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
                newImage = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
                newLength = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
                /* Call the class file reader/write demo code */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
                java_crw_demo(cnum,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
                    classname,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
                    class_data,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
                    class_data_len,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
                    systemClass,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
                    STRING(HEAP_TRACKER_class),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
                    "L" STRING(HEAP_TRACKER_class) ";",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
                    NULL, NULL,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
                    NULL, NULL,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
                    STRING(HEAP_TRACKER_newobj), "(Ljava/lang/Object;)V",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
                    STRING(HEAP_TRACKER_newarr), "(Ljava/lang/Object;)V",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
                    &newImage,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
                    &newLength,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
                    NULL,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
                    NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
                /* If we got back a new class image, return it back as "the"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
                 *   new class image. This must be JVMTI Allocate space.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
                if ( newLength > 0 ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
                    unsigned char *jvmti_space;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
                    jvmti_space = (unsigned char *)allocate(jvmti, (jint)newLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
                    (void)memcpy((void*)jvmti_space, (void*)newImage, (int)newLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
                    *new_class_data_len = (jint)newLength;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
                    *new_class_data     = jvmti_space; /* VM will deallocate */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
                /* Always free up the space we get from java_crw_demo() */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
                if ( newImage != NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
                    (void)free((void*)newImage); /* Free malloc() space with free() */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
            (void)free((void*)classname);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
    } exitCriticalSection(jvmti);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
/* Parse the options for this heapTracker agent */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
parse_agent_options(char *options)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
    #define MAX_TOKEN_LENGTH        16
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
    char  token[MAX_TOKEN_LENGTH];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
    char *next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
    /* Defaults */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
    gdata->maxDump = 20;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
    /* Parse options and set flags in gdata */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
    if ( options==NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
    /* Get the first token from the options string. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
    next = get_token(options, ",=", token, (int)sizeof(token));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
    /* While not at the end of the options string, process this option. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
    while ( next != NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
        if ( strcmp(token,"help")==0 ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
            stdout_message("The heapTracker JVMTI demo agent\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
            stdout_message("\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
            stdout_message(" java -agent:heapTracker[=options] ...\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
            stdout_message("\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
            stdout_message("The options are comma separated:\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
            stdout_message("\t help\t\t\t Print help information\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
            stdout_message("\t maxDump=n\t\t\t How many TraceInfo's to dump\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
            stdout_message("\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
            exit(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
        } else if ( strcmp(token,"maxDump")==0 ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
            char  number[MAX_TOKEN_LENGTH];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
            next = get_token(next, ",=", number, (int)sizeof(number));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
            if ( next == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
                fatal_error("ERROR: Cannot parse maxDump=number: %s\n", options);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
            gdata->maxDump = atoi(number);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
        } else if ( token[0]!=0 ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
            /* We got a non-empty token and we don't know what it is. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
            fatal_error("ERROR: Unknown option: %s\n", token);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
        /* Get the next token (returns NULL if there are no more) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
        next = get_token(next, ",=", token, (int)sizeof(token));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
/* Agent_OnLoad: This is called immediately after the shared library is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
 *   loaded. This is the first code executed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
JNIEXPORT jint JNICALL
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
    static GlobalAgentData data;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
    jvmtiEnv              *jvmti;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
    jvmtiError             error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
    jint                   res;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
    TraceFlavor            flavor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
    jvmtiCapabilities      capabilities;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
    jvmtiEventCallbacks    callbacks;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
    static Trace           empty;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
    /* Setup initial global agent data area
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
     *   Use of static/extern data should be handled carefully here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
     *   We need to make sure that we are able to cleanup after ourselves
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
     *     so anything allocated in this library needs to be freed in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
     *     the Agent_OnUnload() function.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
    (void)memset((void*)&data, 0, sizeof(data));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
    gdata = &data;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
    /* First thing we need to do is get the jvmtiEnv* or JVMTI environment */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
    res = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION_1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
    if (res != JNI_OK) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
        /* This means that the VM was unable to obtain this version of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
         *   JVMTI interface, this is a fatal error.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
        fatal_error("ERROR: Unable to access JVMTI Version 1 (0x%x),"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
                " is your JDK a 5.0 or newer version?"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
                " JNIEnv's GetEnv() returned %d\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
               JVMTI_VERSION_1, res);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
    /* Here we save the jvmtiEnv* for Agent_OnUnload(). */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
    gdata->jvmti = jvmti;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
    /* Parse any options supplied on java command line */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
    parse_agent_options(options);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
    /* Immediately after getting the jvmtiEnv* we need to ask for the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
     *   capabilities this agent will need.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
    (void)memset(&capabilities,0, sizeof(capabilities));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
    capabilities.can_generate_all_class_hook_events = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
    capabilities.can_tag_objects  = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
    capabilities.can_generate_object_free_events  = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
    capabilities.can_get_source_file_name  = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
    capabilities.can_get_line_numbers  = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
    capabilities.can_generate_vm_object_alloc_events  = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
    error = (*jvmti)->AddCapabilities(jvmti, &capabilities);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
    check_jvmti_error(jvmti, error, "Unable to get necessary JVMTI capabilities.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
    /* Next we need to provide the pointers to the callback functions to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
     *   to this jvmtiEnv*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
    (void)memset(&callbacks,0, sizeof(callbacks));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
    /* JVMTI_EVENT_VM_START */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
    callbacks.VMStart           = &cbVMStart;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
    /* JVMTI_EVENT_VM_INIT */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
    callbacks.VMInit            = &cbVMInit;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
    /* JVMTI_EVENT_VM_DEATH */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
    callbacks.VMDeath           = &cbVMDeath;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
    /* JVMTI_EVENT_OBJECT_FREE */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
    callbacks.ObjectFree        = &cbObjectFree;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
    /* JVMTI_EVENT_VM_OBJECT_ALLOC */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
    callbacks.VMObjectAlloc     = &cbVMObjectAlloc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
    /* JVMTI_EVENT_CLASS_FILE_LOAD_HOOK */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
    callbacks.ClassFileLoadHook = &cbClassFileLoadHook;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
    error = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, (jint)sizeof(callbacks));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
    check_jvmti_error(jvmti, error, "Cannot set jvmti callbacks");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
    /* At first the only initial events we are interested in are VM
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
     *   initialization, VM death, and Class File Loads.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
     *   Once the VM is initialized we will request more events.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
    error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
                          JVMTI_EVENT_VM_START, (jthread)NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
    check_jvmti_error(jvmti, error, "Cannot set event notification");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
    error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
                          JVMTI_EVENT_VM_INIT, (jthread)NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
    check_jvmti_error(jvmti, error, "Cannot set event notification");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
    error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
                          JVMTI_EVENT_VM_DEATH, (jthread)NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
    check_jvmti_error(jvmti, error, "Cannot set event notification");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
    error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
                          JVMTI_EVENT_OBJECT_FREE, (jthread)NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
    check_jvmti_error(jvmti, error, "Cannot set event notification");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
    error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
                          JVMTI_EVENT_VM_OBJECT_ALLOC, (jthread)NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
    check_jvmti_error(jvmti, error, "Cannot set event notification");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
    error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
                          JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, (jthread)NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
    check_jvmti_error(jvmti, error, "Cannot set event notification");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   980
90ce3da70b43 Initial load
duke
parents:
diff changeset
   981
    /* Here we create a raw monitor for our use in this agent to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
     *   protect critical sections of code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   983
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   984
    error = (*jvmti)->CreateRawMonitor(jvmti, "agent data", &(gdata->lock));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   985
    check_jvmti_error(jvmti, error, "Cannot create raw monitor");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   986
90ce3da70b43 Initial load
duke
parents:
diff changeset
   987
    /* Create the TraceInfo for various flavors of empty traces */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   988
    for ( flavor = TRACE_FIRST ; flavor <= TRACE_LAST ; flavor++ ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   989
        gdata->emptyTrace[flavor] =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
               newTraceInfo(&empty, hashTrace(&empty), flavor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   992
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
    /* Add jar file to boot classpath */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
    add_demo_jar_to_bootclasspath(jvmti, "heapTracker");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   995
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
    /* We return JNI_OK to signify success */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
    return JNI_OK;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   999
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1000
/* Agent_OnUnload: This is called immediately before the shared library is
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1001
 *   unloaded. This is the last code executed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1002
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1003
JNIEXPORT void JNICALL
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1004
Agent_OnUnload(JavaVM *vm)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1005
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1006
    /* Skip any cleanup, VM is about to die anyway */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1007
}