hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapGXLWriter.java
author coleenp
Wed, 22 May 2013 14:37:49 -0400
changeset 17826 9ad5cd464a75
parent 13728 882756847a04
child 22234 da823d78ad65
permissions -rw-r--r--
8003421: NPG: Move oops out of InstanceKlass into mirror Summary: Inject protection_domain, signers, init_lock into java_lang_Class Reviewed-by: stefank, dholmes, sla
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
13728
882756847a04 6964458: Reimplement class meta-data storage to use native memory
coleenp
parents: 8878
diff changeset
     2
 * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     4
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
489c9b5090e2 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
489c9b5090e2 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     8
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
489c9b5090e2 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
489c9b5090e2 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    14
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
489c9b5090e2 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    18
 *
5547
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1
diff changeset
    21
 * questions.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    22
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    23
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    24
489c9b5090e2 Initial load
duke
parents:
diff changeset
    25
package sun.jvm.hotspot.utilities;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    26
489c9b5090e2 Initial load
duke
parents:
diff changeset
    27
import java.io.*;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    28
import java.util.*;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    29
import sun.jvm.hotspot.oops.*;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    30
import sun.jvm.hotspot.runtime.*;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    31
489c9b5090e2 Initial load
duke
parents:
diff changeset
    32
/**
489c9b5090e2 Initial load
duke
parents:
diff changeset
    33
 * <p>This class writes Java heap in Graph eXchange Language (GXL)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    34
 * format. GXL is an open standard for serializing arbitrary graphs in
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
 * XML syntax.</p>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
 * <p>A GXL document contains one or more graphs. A graph contains
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
 * nodes and edges. Both nodes and edges can have attributes. graphs,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
 * nodes, edges and attributes are represented by XML elements graph,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
 * node, edge and attr respectively. Attributes can be typed. GXL
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
 * supports locator, bool, int, float, bool, string, enum as well as
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
 * set, seq, bag, tup types. Nodes must have a XML attribute 'id' that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
 * is unique id of the node in the GXL document. Edges must have
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
 * 'from' and 'to' XML attributes that are ids of from and to nodes.</p>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
 * <p>Java heap to GXL document mapping:</p>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
 * <ul>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
 * <li>Java object - GXL node.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
 * <li>Java primitive field - GXL attribute (type mapping below).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
 * <li>Java reference field - GXL edge from referee to referent node.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
 * <li>Java primitive array - GXL node with seq type attribute.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
 * <li>Java char array - GXL node with one attribute of string type.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
 * <li>Java object array - GXL node and 'length' edges.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
 * </ul>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
 * <p>Java primitive to GXL type mapping:</p>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
 * <ul>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
 * <li>Java byte, int, short, long - GXL int attribute
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
 * <li>Java float, double - GXL float attribute
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
 * <li>Java boolean - GXL bool atttribute
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
 * <li>Java char - GXL string attribute
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
 * </ul>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
 * Exact Java primitive type code is written in 'kind' attribute of
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
 * 'attr' element.  Type code is specified in JVM spec. second edition
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
 * section 4.3.2 (Field Descriptor).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
 * @see <a href="http://www.gupro.de/GXL/">GXL</a>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
 * @see <a href="http://www.gupro.de/GXL/dtd/dtd.html">GXL DTD</a>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
public class HeapGXLWriter extends AbstractHeapGraphWriter {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
    public void write(String fileName) throws IOException {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
        out = new PrintWriter(new BufferedWriter(new FileWriter(fileName)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
        super.write();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
        if (out.checkError()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
            throw new IOException();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
        out.flush();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
    protected void writeHeapHeader() throws IOException {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
        // XML processing instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
        out.print("<?xml version='1.0' encoding='");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
        out.print(ENCODING);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
        out.println("'?>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
        out.println("<gxl>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
        out.println("<graph id='JavaHeap'>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
        // document properties
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
        writeAttribute("creation-date", "string", new Date().toString());
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
        // write VM info
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
        writeVMInfo();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
        // emit a node for null
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
        out.print("<node id='");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
        out.print(getID(null));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
        out.println("'/>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
    protected void writeObjectHeader(Oop oop) throws IOException  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
        refFields = new ArrayList();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
        isArray = oop.isArray();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
        // generate an edge for instanceof relation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
        // between object node and it's class node.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
        writeEdge(oop, oop.getKlass().getJavaMirror(), "instanceof");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
        out.print("<node id='");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
        out.print(getID(oop));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
        out.println("'>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
    protected void writeObjectFooter(Oop oop) throws IOException  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
        out.println("</node>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
        // write the reference fields as edges
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
        for (Iterator itr = refFields.iterator(); itr.hasNext();) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
            OopField field = (OopField) itr.next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
            Oop ref = field.getValue(oop);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
            String name = field.getID().getName();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
            if (isArray) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
                // for arrays elements we use element<index> pattern
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
                name = "element" + name;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
            } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
                name = identifierToXMLName(name);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
            }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
            writeEdge(oop, ref, name);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
        refFields = null;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
    protected void writeObjectArray(ObjArray array) throws IOException {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
        writeObjectHeader(array);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
        writeArrayLength(array);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
        writeObjectFields(array);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
        writeObjectFooter(array);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
    protected void writePrimitiveArray(TypeArray array)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
        throws IOException  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
        writeObjectHeader(array);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
        // write array length
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
        writeArrayLength(array);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
        // write array elements
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
        out.println("\t<attr name='elements'>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
        TypeArrayKlass klass = (TypeArrayKlass) array.getKlass();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
        if (klass.getElementType() == TypeArrayKlass.T_CHAR) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
            // char[] special treatment -- write it as string
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
            out.print("\t<string>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
            out.print(escapeXMLChars(OopUtilities.charArrayToString(array)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
            out.println("</string>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
            out.println("\t<seq>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
            writeObjectFields(array);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
            out.println("\t</seq>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
        out.println("\t</attr>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
        writeObjectFooter(array);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
    protected void writeClass(Instance instance) throws IOException  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   166
        writeObjectHeader(instance);
8878
a6283814032c 7031614: jmap -permstat fails with java.lang.InternalError in sun.jvm.hotspot.oops.OopField.getValue
never
parents: 5547
diff changeset
   167
        Klass reflectedType = java_lang_Class.asKlass(instance);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
        boolean isInstanceKlass = (reflectedType instanceof InstanceKlass);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   169
        // reflectedType is null for primitive types (int.class etc).
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
        if (reflectedType != null) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
            Symbol name = reflectedType.getName();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
            if (name != null) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
                // write class name as an attribute
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
                writeAttribute("class-name", "string", name.asString());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
            }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
            if (isInstanceKlass) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   177
                // write object-size as an attribute
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
                long sizeInBytes = reflectedType.getLayoutHelper();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
                writeAttribute("object-size", "int",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
                               Long.toString(sizeInBytes));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
                // write static fields of this class.
13728
882756847a04 6964458: Reimplement class meta-data storage to use native memory
coleenp
parents: 8878
diff changeset
   182
                writeObjectFields((InstanceKlass)reflectedType);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
            }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   184
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
        out.println("</node>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
        // write edges for super class and direct interfaces
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
        if (reflectedType != null) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   189
            Klass superType = reflectedType.getSuper();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   190
            Oop superMirror = (superType == null)?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
                              null : superType.getJavaMirror();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
            writeEdge(instance, superMirror, "extends");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
            if (isInstanceKlass) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
                // write edges for directly implemented interfaces
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
                InstanceKlass ik = (InstanceKlass) reflectedType;
13728
882756847a04 6964458: Reimplement class meta-data storage to use native memory
coleenp
parents: 8878
diff changeset
   196
                KlassArray interfaces = ik.getLocalInterfaces();
882756847a04 6964458: Reimplement class meta-data storage to use native memory
coleenp
parents: 8878
diff changeset
   197
                final int len = interfaces.length();
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
                for (int i = 0; i < len; i++) {
13728
882756847a04 6964458: Reimplement class meta-data storage to use native memory
coleenp
parents: 8878
diff changeset
   199
                    Klass k = interfaces.getAt(i);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
                    writeEdge(instance, k.getJavaMirror(), "implements");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
                }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
                // write loader
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
                Oop loader = ik.getClassLoader();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
                writeEdge(instance, loader, "loaded-by");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
17826
9ad5cd464a75 8003421: NPG: Move oops out of InstanceKlass into mirror
coleenp
parents: 13728
diff changeset
   207
                // write signers NYI
9ad5cd464a75 8003421: NPG: Move oops out of InstanceKlass into mirror
coleenp
parents: 13728
diff changeset
   208
                // Oop signers = ik.getJavaMirror().getSigners();
9ad5cd464a75 8003421: NPG: Move oops out of InstanceKlass into mirror
coleenp
parents: 13728
diff changeset
   209
                writeEdge(instance, null, "signed-by");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
17826
9ad5cd464a75 8003421: NPG: Move oops out of InstanceKlass into mirror
coleenp
parents: 13728
diff changeset
   211
                // write protection domain NYI
9ad5cd464a75 8003421: NPG: Move oops out of InstanceKlass into mirror
coleenp
parents: 13728
diff changeset
   212
                // Oop protectionDomain = ik.getJavaMirror().getProtectionDomain();
9ad5cd464a75 8003421: NPG: Move oops out of InstanceKlass into mirror
coleenp
parents: 13728
diff changeset
   213
                writeEdge(instance, null, "protection-domain");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   214
489c9b5090e2 Initial load
duke
parents:
diff changeset
   215
                // write edges for static reference fields from this class
489c9b5090e2 Initial load
duke
parents:
diff changeset
   216
                for (Iterator itr = refFields.iterator(); itr.hasNext();) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   217
                    OopField field = (OopField) itr.next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   218
                    Oop ref = field.getValue(reflectedType);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   219
                    String name = field.getID().getName();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   220
                    writeEdge(instance, ref, identifierToXMLName(name));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   221
                }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   222
            }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   223
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   224
        refFields = null;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   225
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   226
489c9b5090e2 Initial load
duke
parents:
diff changeset
   227
    protected void writeReferenceField(Oop oop, OopField field)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   228
        throws IOException {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   229
        refFields.add(field);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   230
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   231
489c9b5090e2 Initial load
duke
parents:
diff changeset
   232
    protected void writeByteField(Oop oop, ByteField field)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   233
        throws IOException {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   234
        writeField(field, "int", "B", Byte.toString(field.getValue(oop)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   235
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   236
489c9b5090e2 Initial load
duke
parents:
diff changeset
   237
    protected void writeCharField(Oop oop, CharField field)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   238
        throws IOException {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   239
        writeField(field, "string", "C",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   240
                   escapeXMLChars(Character.toString(field.getValue(oop))));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   241
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   242
489c9b5090e2 Initial load
duke
parents:
diff changeset
   243
    protected void writeBooleanField(Oop oop, BooleanField field)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   244
        throws IOException {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   245
        writeField(field, "bool", "Z", Boolean.toString(field.getValue(oop)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   246
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   247
489c9b5090e2 Initial load
duke
parents:
diff changeset
   248
    protected void writeShortField(Oop oop, ShortField field)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   249
        throws IOException {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   250
        writeField(field, "int", "S", Short.toString(field.getValue(oop)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   251
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   252
489c9b5090e2 Initial load
duke
parents:
diff changeset
   253
    protected void writeIntField(Oop oop, IntField field)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   254
        throws IOException {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   255
        writeField(field, "int", "I", Integer.toString(field.getValue(oop)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   256
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   257
489c9b5090e2 Initial load
duke
parents:
diff changeset
   258
    protected void writeLongField(Oop oop, LongField field)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   259
        throws IOException {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   260
        writeField(field, "int", "J", Long.toString(field.getValue(oop)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   261
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   262
489c9b5090e2 Initial load
duke
parents:
diff changeset
   263
    protected void writeFloatField(Oop oop, FloatField field)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   264
        throws IOException {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   265
        writeField(field, "float", "F", Float.toString(field.getValue(oop)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   266
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   267
489c9b5090e2 Initial load
duke
parents:
diff changeset
   268
    protected void writeDoubleField(Oop oop, DoubleField field)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   269
        throws IOException {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   270
        writeField(field, "float", "D", Double.toString(field.getValue(oop)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   271
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   272
489c9b5090e2 Initial load
duke
parents:
diff changeset
   273
    protected void writeHeapFooter() throws IOException  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   274
        out.println("</graph>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   275
        out.println("</gxl>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   276
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   277
489c9b5090e2 Initial load
duke
parents:
diff changeset
   278
    //-- Internals only below this point
489c9b5090e2 Initial load
duke
parents:
diff changeset
   279
489c9b5090e2 Initial load
duke
parents:
diff changeset
   280
    // Java identifier to XML NMTOKEN type string
489c9b5090e2 Initial load
duke
parents:
diff changeset
   281
    private static String identifierToXMLName(String name) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   282
        // for now, just replace '$' with '_'
489c9b5090e2 Initial load
duke
parents:
diff changeset
   283
        return name.replace('$', '_');
489c9b5090e2 Initial load
duke
parents:
diff changeset
   284
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   285
489c9b5090e2 Initial load
duke
parents:
diff changeset
   286
    // escapes XML meta-characters and illegal characters
489c9b5090e2 Initial load
duke
parents:
diff changeset
   287
    private static String escapeXMLChars(String s) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   288
        // FIXME: is there a better way or API?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   289
        StringBuffer result = null;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   290
        for(int i = 0, max = s.length(), delta = 0; i < max; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   291
            char c = s.charAt(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   292
            String replacement = null;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   293
            if (c == '&') {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   294
                replacement = "&amp;";
489c9b5090e2 Initial load
duke
parents:
diff changeset
   295
            } else if (c == '<') {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   296
                replacement = "&lt;";
489c9b5090e2 Initial load
duke
parents:
diff changeset
   297
            } else if (c == '>') {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   298
                replacement = "&gt;";
489c9b5090e2 Initial load
duke
parents:
diff changeset
   299
            } else if (c == '"') {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   300
                replacement = "&quot;";
489c9b5090e2 Initial load
duke
parents:
diff changeset
   301
            } else if (c == '\'') {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   302
                replacement = "&apos;";
489c9b5090e2 Initial load
duke
parents:
diff changeset
   303
            } else if (c <  '\u0020' || (c > '\ud7ff' && c < '\ue000') ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   304
                       c == '\ufffe' || c == '\uffff') {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   305
                // These are illegal in XML -- put these in a CDATA section.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   306
                // Refer to section 2.2 Characters in XML specification at
489c9b5090e2 Initial load
duke
parents:
diff changeset
   307
                // http://www.w3.org/TR/2004/REC-xml-20040204/
489c9b5090e2 Initial load
duke
parents:
diff changeset
   308
                replacement = "<![CDATA[&#x" +
489c9b5090e2 Initial load
duke
parents:
diff changeset
   309
                    Integer.toHexString((int)c) + ";]]>";
489c9b5090e2 Initial load
duke
parents:
diff changeset
   310
            }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   311
489c9b5090e2 Initial load
duke
parents:
diff changeset
   312
            if (replacement != null) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   313
                if (result == null) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   314
                    result = new StringBuffer(s);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   315
                }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   316
                result.replace(i + delta, i + delta + 1, replacement);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   317
                delta += (replacement.length() - 1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   318
            }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   319
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   320
        if (result == null) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   321
            return s;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   322
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   323
        return result.toString();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   324
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   325
489c9b5090e2 Initial load
duke
parents:
diff changeset
   326
    private static String getID(Oop oop) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   327
        // address as unique id for node -- prefixed by "ID_".
489c9b5090e2 Initial load
duke
parents:
diff changeset
   328
        if (oop == null) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   329
            return "ID_NULL";
489c9b5090e2 Initial load
duke
parents:
diff changeset
   330
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   331
            return "ID_" + oop.getHandle().toString();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   332
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   333
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   334
489c9b5090e2 Initial load
duke
parents:
diff changeset
   335
    private void writeArrayLength(Array array) throws IOException {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   336
        writeAttribute("length", "int",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   337
                       Integer.toString((int) array.getLength()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   338
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   339
489c9b5090e2 Initial load
duke
parents:
diff changeset
   340
    private void writeAttribute(String name, String type, String value) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   341
        out.print("\t<attr name='");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   342
        out.print(name);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   343
        out.print("'><");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   344
        out.print(type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   345
        out.print('>');
489c9b5090e2 Initial load
duke
parents:
diff changeset
   346
        out.print(value);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   347
        out.print("</");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   348
        out.print(type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   349
        out.println("></attr>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   350
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   351
489c9b5090e2 Initial load
duke
parents:
diff changeset
   352
    private void writeEdge(Oop from, Oop to, String name) throws IOException {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   353
        out.print("<edge from='");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   354
        out.print(getID(from));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   355
        out.print("' to='");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   356
        out.print(getID(to));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   357
        out.println("'>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   358
        writeAttribute("name", "string", name);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   359
        out.println("</edge>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   360
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   361
489c9b5090e2 Initial load
duke
parents:
diff changeset
   362
    private void writeField(Field field, String type, String kind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   363
                            String value) throws IOException  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   364
        // 'type' is GXL type of the attribute
489c9b5090e2 Initial load
duke
parents:
diff changeset
   365
        // 'kind' is Java type code ("B", "C", "Z", "S", "I", "J", "F", "D")
489c9b5090e2 Initial load
duke
parents:
diff changeset
   366
        if (isArray) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   367
            out.print('\t');
489c9b5090e2 Initial load
duke
parents:
diff changeset
   368
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   369
            out.print("\t<attr name='");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   370
            String name = field.getID().getName();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   371
            out.print(identifierToXMLName(name));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   372
            out.print("' kind='");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   373
            out.print(kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   374
            out.print("'>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   375
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   376
        out.print('<');
489c9b5090e2 Initial load
duke
parents:
diff changeset
   377
        out.print(type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   378
        out.print('>');
489c9b5090e2 Initial load
duke
parents:
diff changeset
   379
        out.print(value);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   380
        out.print("</");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   381
        out.print(type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   382
        out.print('>');
489c9b5090e2 Initial load
duke
parents:
diff changeset
   383
        if (isArray) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   384
            out.println();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   385
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   386
            out.println("</attr>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   387
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   388
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   389
489c9b5090e2 Initial load
duke
parents:
diff changeset
   390
    private void writeVMInfo() throws IOException {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   391
        VM vm = VM.getVM();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   392
        writeAttribute("vm-version", "string", vm.getVMRelease());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   393
        writeAttribute("vm-type", "string",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   394
                       (vm.isClientCompiler())? "client" :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   395
                       ((vm.isServerCompiler())? "server" : "core"));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   396
        writeAttribute("os", "string", vm.getOS());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   397
        writeAttribute("cpu", "string", vm.getCPU());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   398
        writeAttribute("pointer-size", "string",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   399
                       Integer.toString((int)vm.getOopSize() * 8));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   400
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   401
489c9b5090e2 Initial load
duke
parents:
diff changeset
   402
    // XML encoding that we'll use
489c9b5090e2 Initial load
duke
parents:
diff changeset
   403
    private static final String ENCODING = "UTF-8";
489c9b5090e2 Initial load
duke
parents:
diff changeset
   404
489c9b5090e2 Initial load
duke
parents:
diff changeset
   405
    // reference fields of currently visited object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   406
    private List/*<OopField>*/ refFields;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   407
    // are we writing an array now?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   408
    private boolean isArray;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   409
    private PrintWriter out;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   410
}