1 /*
   2  * Copyright (c) 2002, 2013, 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 
  25 package sun.jvm.hotspot.tools.jcore;
  26 
  27 import java.io.*;
  28 import java.lang.reflect.Constructor;
  29 import java.util.jar.JarOutputStream;
  30 import java.util.jar.JarEntry;
  31 import java.util.jar.Manifest;
  32 import sun.jvm.hotspot.classfile.*;
  33 import sun.jvm.hotspot.memory.*;
  34 import sun.jvm.hotspot.oops.*;
  35 import sun.jvm.hotspot.debugger.*;
  36 import sun.jvm.hotspot.runtime.*;
  37 import sun.jvm.hotspot.tools.*;
  38 
  39 public 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 }