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