jdk/src/jdk.jcmd/share/classes/sun/tools/jmap/JMap.java
author lana
Mon, 30 Nov 2015 13:27:57 -0800
changeset 34476 9f12a05b4786
parent 25859 3317bb8137f4
child 36511 9d0388c6b336
permissions -rw-r--r--
Merge
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
16501
678abe06c15c 8005116: NPG: Rename -permstat option for jmap in jdk8 to -clstats
stefank
parents: 14342
diff changeset
     2
 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1247
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1247
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1247
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1247
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1247
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.tools.jmap;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.lang.reflect.Method;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.io.File;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.io.IOException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.io.InputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import com.sun.tools.attach.VirtualMachine;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import com.sun.tools.attach.AttachNotSupportedException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import sun.tools.attach.HotSpotVirtualMachine;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
 * This class is the main class for the JMap utility. It parses its arguments
21278
ef8a3a2a72f2 8022746: List of spelling errors in API doc
malenkov
parents: 16501
diff changeset
    39
 * and decides if the command should be satisfied using the VM attach mechanism
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
 * or an SA tool. At this time the only option that uses the VM attach mechanism
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
 * is the -dump option to get a heap dump of a running application. All other
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
 * options are mapped to SA tools.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
public class JMap {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
    // Options handled by the attach mechanism
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
    private static String HISTO_OPTION = "-histo";
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
    private static String LIVE_HISTO_OPTION = "-histo:live";
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
    private static String DUMP_OPTION_PREFIX = "-dump:";
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
    // These options imply the use of a SA tool
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
    private static String SA_TOOL_OPTIONS =
16501
678abe06c15c 8005116: NPG: Rename -permstat option for jmap in jdk8 to -clstats
stefank
parents: 14342
diff changeset
    53
      "-heap|-heap:format=b|-clstats|-finalizerinfo";
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
    // The -F (force) option is currently not passed through to SA
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
    private static String FORCE_SA_OPTION = "-F";
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
    // Default option (if nothing provided)
1089
12e2f9ad0367 6653883: jmap with no option should print mmap instead of heap information.
swamyv
parents: 2
diff changeset
    59
    private static String DEFAULT_OPTION = "-pmap";
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
    public static void main(String[] args) throws Exception {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
        if (args.length == 0) {
21673
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
    63
            usage(1); // no arguments
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
        // used to indicate if we should use SA
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
        boolean useSA = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
        // the chosen option (-heap, -dump:*, ... )
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
        String option = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
        // First iterate over the options (arguments starting with -).  There should be
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
        // one (but maybe two if -F is also used).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
        int optionCount = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
        while (optionCount < args.length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
            String arg = args[optionCount];
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
            if (!arg.startsWith("-")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
            }
21673
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
    80
            if (arg.equals("-help") || arg.equals("-h")) {
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
    81
                usage(0);
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
    82
            } else if (arg.equals(FORCE_SA_OPTION)) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
                useSA = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
                if (option != null) {
21673
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
    86
                    usage(1);  // option already specified
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
                option = arg;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
            optionCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
        // if no option provided then use default.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
        if (option == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
            option = DEFAULT_OPTION;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
        if (option.matches(SA_TOOL_OPTIONS)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
            useSA = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
        // Next we check the parameter count. For the SA tools there are
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
        // one or two parameters. For the built-in -dump option there is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
        // only one parameter (the process-id)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
        int paramCount = args.length - optionCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
        if (paramCount == 0 || paramCount > 2) {
21673
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   106
            usage(1);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
        if (optionCount == 0 || paramCount != 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
            useSA = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
            // the parameter for the -dump option is a process-id.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
            // If it doesn't parse to a number then it must be SA
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
            // debug server
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
            if (!args[optionCount].matches("[0-9]+")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
                useSA = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
        // at this point we know if we are executing an SA tool or a built-in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
        // option.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
        if (useSA) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
            // parameters (<pid> or <exe> <core>)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
            String params[] = new String[paramCount];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
            for (int i=optionCount; i<args.length; i++ ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
                params[i-optionCount] = args[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
            runTool(option, params);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
            String pid = args[1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
            // Here we handle the built-in options
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
            // As more options are added we should create an abstract tool class and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
            // have a table to map the options
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
            if (option.equals(HISTO_OPTION)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
                histo(pid, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
            } else if (option.equals(LIVE_HISTO_OPTION)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
                histo(pid, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
            } else if (option.startsWith(DUMP_OPTION_PREFIX)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
                dump(pid, option);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
            } else {
21673
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   144
                usage(1);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
    // Invoke SA tool  with the given arguments
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
    private static void runTool(String option, String args[]) throws Exception {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
        String[][] tools = {
16501
678abe06c15c 8005116: NPG: Rename -permstat option for jmap in jdk8 to -clstats
stefank
parents: 14342
diff changeset
   152
            { "-pmap",          "sun.jvm.hotspot.tools.PMap"             },
678abe06c15c 8005116: NPG: Rename -permstat option for jmap in jdk8 to -clstats
stefank
parents: 14342
diff changeset
   153
            { "-heap",          "sun.jvm.hotspot.tools.HeapSummary"      },
678abe06c15c 8005116: NPG: Rename -permstat option for jmap in jdk8 to -clstats
stefank
parents: 14342
diff changeset
   154
            { "-heap:format=b", "sun.jvm.hotspot.tools.HeapDumper"       },
678abe06c15c 8005116: NPG: Rename -permstat option for jmap in jdk8 to -clstats
stefank
parents: 14342
diff changeset
   155
            { "-histo",         "sun.jvm.hotspot.tools.ObjectHistogram"  },
678abe06c15c 8005116: NPG: Rename -permstat option for jmap in jdk8 to -clstats
stefank
parents: 14342
diff changeset
   156
            { "-clstats",       "sun.jvm.hotspot.tools.ClassLoaderStats" },
678abe06c15c 8005116: NPG: Rename -permstat option for jmap in jdk8 to -clstats
stefank
parents: 14342
diff changeset
   157
            { "-finalizerinfo", "sun.jvm.hotspot.tools.FinalizerInfo"    },
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
        };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
        String tool = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
        // -dump option needs to be handled in a special way
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
        if (option.startsWith(DUMP_OPTION_PREFIX)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
            // first check that the option can be parsed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
            String fn = parseDumpOptions(option);
21673
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   166
            if (fn == null) {
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   167
                usage(1);
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   168
            }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
            // tool for heap dumping
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
            tool = "sun.jvm.hotspot.tools.HeapDumper";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
            // HeapDumper -f <file>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
            args = prepend(fn, args);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
            args = prepend("-f", args);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
            int i=0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
            while (i < tools.length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
                if (option.equals(tools[i][0])) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
                    tool = tools[i][1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
                i++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
        if (tool == null) {
21673
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   187
            usage(1);   // no mapping to tool
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
        // Tool not available on this  platform.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
        Class<?> c = loadClass(tool);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        if (c == null) {
21673
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   193
            usage(1);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
        // invoke the main method with the arguments
24871
224e298c3978 8044865: Fix raw and unchecked lint warnings in management-related code
sjiang
parents: 21673
diff changeset
   197
        Class<?>[] argTypes = { String[].class } ;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
        Method m = c.getDeclaredMethod("main", argTypes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
        Object[] invokeArgs = { args };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
        m.invoke(null, invokeArgs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
    // loads the given class using the system class loader
11125
99b115114fa3 7117357: Warnings in sun.instrument, tools and other sun.* classes
alanb
parents: 5506
diff changeset
   205
    private static Class<?> loadClass(String name) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
        // We specify the system clas loader so as to cater for development
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
        // environments where this class is on the boot class path but sa-jdi.jar
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
        // is on the system class path. Once the JDK is deployed then both
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
        // tools.jar and sa-jdi.jar are on the system class path.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
            return Class.forName(name, true,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
                                 ClassLoader.getSystemClassLoader());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
        } catch (Exception x)  { }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
    private static final String LIVE_OBJECTS_OPTION = "-live";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
    private static final String ALL_OBJECTS_OPTION = "-all";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
    private static void histo(String pid, boolean live) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
        VirtualMachine vm = attach(pid);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
        InputStream in = ((HotSpotVirtualMachine)vm).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
            heapHisto(live ? LIVE_OBJECTS_OPTION : ALL_OBJECTS_OPTION);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
        drain(vm, in);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
    private static void dump(String pid, String options) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
        // parse the options to get the dump filename
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
        String filename = parseDumpOptions(options);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
        if (filename == null) {
21673
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   232
            usage(1);  // invalid options or no filename
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
        // get the canonical path - important to avoid just passing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
        // a "heap.bin" and having the dump created in the target VM
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
        // working directory rather than the directory where jmap
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
        // is executed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
        filename = new File(filename).getCanonicalPath();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
        // dump live objects only or not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
        boolean live = isDumpLiveObjects(options);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
        VirtualMachine vm = attach(pid);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
        System.out.println("Dumping heap to " + filename + " ...");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
        InputStream in = ((HotSpotVirtualMachine)vm).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
            dumpHeap((Object)filename,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
                     (live ? LIVE_OBJECTS_OPTION : ALL_OBJECTS_OPTION));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
        drain(vm, in);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
    // Parse the options to the -dump option. Valid options are format=b and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
    // file=<file>. Returns <file> if provided. Returns null if <file> not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
    // provided, or invalid option.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
    private static String parseDumpOptions(String arg) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
        assert arg.startsWith(DUMP_OPTION_PREFIX);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
        String filename = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
        // options are separated by comma (,)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
        String options[] = arg.substring(DUMP_OPTION_PREFIX.length()).split(",");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
        for (int i=0; i<options.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
            String option = options[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
            if (option.equals("format=b")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
                // ignore format (not needed at this time)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
            } else if (option.equals("live")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
                // a valid suboption
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
                // file=<file> - check that <file> is specified
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
                if (option.startsWith("file=")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
                    filename = option.substring(5);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
                    if (filename.length() == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
                        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
                    return null;  // option not recognized
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
        return filename;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
    private static boolean isDumpLiveObjects(String arg) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
        // options are separated by comma (,)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
        String options[] = arg.substring(DUMP_OPTION_PREFIX.length()).split(",");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
        for (String suboption : options) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
            if (suboption.equals("live")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
                return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
    // Attach to <pid>, existing if we fail to attach
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
    private static VirtualMachine attach(String pid) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
            return VirtualMachine.attach(pid);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
        } catch (Exception x) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
            String msg = x.getMessage();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
            if (msg != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
                System.err.println(pid + ": " + msg);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
                x.printStackTrace();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
            if ((x instanceof AttachNotSupportedException) && haveSA()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
                System.err.println("The -F option can be used when the " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
                  "target process is not responding");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
            System.exit(1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
            return null; // keep compiler happy
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
    // Read the stream from the target VM until EOF, then detach
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
    private static void drain(VirtualMachine vm, InputStream in) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
        // read to EOF and just print output
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
        byte b[] = new byte[256];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
        int n;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
        do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
            n = in.read(b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
            if (n > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
                String s = new String(b, 0, n, "UTF-8");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
                System.out.print(s);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
        } while (n > 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
        in.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
        vm.detach();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
    // return a new string array with arg as the first element
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
    private static String[] prepend(String arg, String args[]) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
        String[] newargs = new String[args.length+1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
        newargs[0] = arg;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
        System.arraycopy(args, 0, newargs, 1, args.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
        return newargs;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
    // returns true if SA is available
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
    private static boolean haveSA() {
11125
99b115114fa3 7117357: Warnings in sun.instrument, tools and other sun.* classes
alanb
parents: 5506
diff changeset
   343
        Class<?> c = loadClass("sun.jvm.hotspot.tools.HeapSummary");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
        return (c != null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
    // print usage message
21673
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   348
    private static void usage(int exit) {
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   349
        System.err.println("Usage:");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
        if (haveSA()) {
21673
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   351
            System.err.println("    jmap [option] <pid>");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   352
            System.err.println("        (to connect to running process)");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   353
            System.err.println("    jmap [option] <executable <core>");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   354
            System.err.println("        (to connect to a core file)");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   355
            System.err.println("    jmap [option] [server_id@]<remote server IP or hostname>");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   356
            System.err.println("        (to connect to remote debug server)");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   357
            System.err.println("");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   358
            System.err.println("where <option> is one of:");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   359
            System.err.println("    <none>               to print same info as Solaris pmap");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   360
            System.err.println("    -heap                to print java heap summary");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   361
            System.err.println("    -histo[:live]        to print histogram of java object heap; if the \"live\"");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   362
            System.err.println("                         suboption is specified, only count live objects");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   363
            System.err.println("    -clstats             to print class loader statistics");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   364
            System.err.println("    -finalizerinfo       to print information on objects awaiting finalization");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   365
            System.err.println("    -dump:<dump-options> to dump java heap in hprof binary format");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   366
            System.err.println("                         dump-options:");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   367
            System.err.println("                           live         dump only live objects; if not specified,");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   368
            System.err.println("                                        all objects in the heap are dumped.");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   369
            System.err.println("                           format=b     binary format");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   370
            System.err.println("                           file=<file>  dump heap to <file>");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   371
            System.err.println("                         Example: jmap -dump:live,format=b,file=heap.bin <pid>");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   372
            System.err.println("    -F                   force. Use with -dump:<dump-options> <pid> or -histo");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   373
            System.err.println("                         to force a heap dump or histogram when <pid> does not");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   374
            System.err.println("                         respond. The \"live\" suboption is not supported");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   375
            System.err.println("                         in this mode.");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   376
            System.err.println("    -h | -help           to print this help message");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   377
            System.err.println("    -J<flag>             to pass <flag> directly to the runtime system");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
        } else {
21673
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   379
            System.err.println("    jmap -histo <pid>");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   380
            System.err.println("      (to connect to running process and print histogram of java object heap");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   381
            System.err.println("    jmap -dump:<dump-options> <pid>");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   382
            System.err.println("      (to connect to running process and dump java heap)");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   383
            System.err.println("");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   384
            System.err.println("    dump-options:");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   385
            System.err.println("      format=b     binary default");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   386
            System.err.println("      file=<file>  dump heap to <file>");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   387
            System.err.println("");
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   388
            System.err.println("    Example:       jmap -dump:format=b,file=heap.bin <pid>");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
21673
c5d341bc60dd 8027765: Make exit codes and stdout/stderr printing from jmap/jinfo/jstack/jps consistent
sla
parents: 21278
diff changeset
   391
        System.exit(exit);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
}