1/*
2 * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25package sun.jvm.hotspot.tools.jcore;
26
27import java.io.*;
28import java.lang.reflect.Constructor;
29import java.util.jar.JarOutputStream;
30import java.util.jar.JarEntry;
31import java.util.jar.Manifest;
32import sun.jvm.hotspot.classfile.*;
33import sun.jvm.hotspot.memory.*;
34import sun.jvm.hotspot.oops.*;
35import sun.jvm.hotspot.debugger.*;
36import sun.jvm.hotspot.runtime.*;
37import sun.jvm.hotspot.tools.*;
38
39public class ClassDump extends Tool {
40    private ClassFilter classFilter;
41    private String      outputDirectory;
42    private JarOutputStream jarStream;
43    private String      pkgList;
44
45    public ClassDump() {
46        super();
47    }
48
49    public ClassDump(JVMDebugger d, String pkgList) {
50        super(d);
51        this.pkgList = pkgList;
52    }
53
54    public void setClassFilter(ClassFilter cf) {
55        classFilter = cf;
56    }
57
58    public void setOutputDirectory(String od) {
59        outputDirectory = od;
60        if (jarStream != null) {
61            try {
62                jarStream.close();
63            } catch (IOException ioe) {
64                ioe.printStackTrace();
65            }
66        }
67        jarStream = null;
68    }
69
70    public void setJarOutput(String jarFileName) throws IOException {
71        jarStream = new JarOutputStream(new FileOutputStream(jarFileName), new Manifest());
72        outputDirectory = null;
73    }
74
75    public void run() {
76        // Ready to go with the database...
77        try {
78            if (classFilter == null) {
79                // If not already set, the name of the filter comes from a System property.
80                // If we have a pkgList, pass it, otherwise let the filter read
81                // its own System property for the list of classes.
82                String filterClassName = System.getProperty("sun.jvm.hotspot.tools.jcore.filter",
83                                                            "sun.jvm.hotspot.tools.jcore.PackageNameFilter");
84                try {
85                    Class filterClass = Class.forName(filterClassName);
86                    if (pkgList == null) {
87                        classFilter = (ClassFilter) filterClass.newInstance();
88                    } else {
89                        Constructor con = filterClass.getConstructor(String.class);
90                        classFilter = (ClassFilter) con.newInstance(pkgList);
91                    }
92                } catch(Exception exp) {
93                    System.err.println("Warning: Can not create class filter!");
94                }
95            }
96
97            // outputDirectory and jarStream are alternatives: setting one closes the other.
98            // If neither is set, use outputDirectory from the System property:
99            if (outputDirectory == null && jarStream == null) {
100                String dirName = System.getProperty("sun.jvm.hotspot.tools.jcore.outputDir", ".");
101                setOutputDirectory(dirName);
102            }
103
104            // walk through the loaded classes
105            ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
106            cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
107                    public void visit(Klass k) {
108                        if (k instanceof InstanceKlass) {
109                            try {
110                                dumpKlass((InstanceKlass) k);
111                            } catch (Exception e) {
112                                System.out.println(k.getName().asString());
113                                e.printStackTrace();
114                            }
115                        }
116                    }
117                });
118        }
119        catch (AddressException e) {
120            System.err.println("Error accessing address 0x"
121                               + Long.toHexString(e.getAddress()));
122            e.printStackTrace();
123        }
124        if (jarStream != null) {
125            try {
126                jarStream.close();
127            } catch (IOException ioe) {
128                ioe.printStackTrace();
129            }
130            jarStream = null;
131        }
132    }
133
134    public String getName() {
135        return "jcore";
136    }
137
138    private void dumpKlass(InstanceKlass kls) {
139        if (classFilter != null && ! classFilter.canInclude(kls) ) {
140            return;
141        }
142
143        String klassName = kls.getName().asString();
144        klassName = klassName.replace('/', File.separatorChar);
145        try {
146            OutputStream os = null;
147            if (jarStream != null) {
148                jarStream.putNextEntry(new JarEntry(klassName + ".class"));
149                os = jarStream;
150            } else {
151                int index = klassName.lastIndexOf(File.separatorChar);
152                File dir = null;
153                if (index != -1) {
154                    String dirName = klassName.substring(0, index);
155                    dir = new File(outputDirectory,  dirName);
156                } else {
157                    dir = new File(outputDirectory);
158                }
159
160                dir.mkdirs();
161                File f = new File(dir, klassName.substring(index + 1) + ".class");
162                f.createNewFile();
163                os = new BufferedOutputStream(new FileOutputStream(f));
164            }
165            try {
166                ClassWriter cw = new ClassWriter(kls, os);
167                cw.write();
168            } finally {
169                if (os != jarStream) {
170                    os.close();
171                }
172            }
173        } catch(IOException exp) {
174            exp.printStackTrace();
175        }
176    }
177
178    public static void main(String[] args) {
179
180        ClassDump cd = new ClassDump();
181        cd.execute(args);
182    }
183}
184