通过HotSpot的Serviceability Agent 导出JVM Class文件

 

 

Hotspot 的 Serviceability Agent  是个很强大的JVM 监控工具集合(这里简称SA),我们可以通过SA 提供的Java API(sa-jdi.jar)做很多有趣的事情。今天我们就通过SA的API导出 JVM实例中加载的Class文件。

 

1、编写测试类DumpClassTest

public class DumpClassTest{
     public static void main(String[] args){
          while(true){
               try{
                   Thread.sleep(1000);
               }catche(Exception e){}
          }
     }
}

 2、编写DumpClass类,该类依赖

/home/tools/jdk1.6.0_43/lib/sa-jdi.jar

 

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;

import sun.jvm.hotspot.bugspot.BugSpotAgent;
import sun.jvm.hotspot.memory.SystemDictionary;
import sun.jvm.hotspot.oops.InstanceKlass;
import sun.jvm.hotspot.oops.Klass;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.tools.jcore.ClassWriter;


public class DumpVMClass {
	

	
	private static JarOutputStream jarStream;
	//导出目录地址
	private static String outputDirectory = "/home/tools/jdk1.6.0_43/class/";
	
	public static void main(String[] args){
		BugSpotAgent agent = new BugSpotAgent();
		try {
			int pid = Integer.parseInt(args[0]);
			agent.attach(pid);
			boolean isJavaMode = agent.isJavaMode();
			if(isJavaMode){
				SystemDictionary dict = VM.getVM().getSystemDictionary();
				dict.classesDo(new SystemDictionary.ClassVisitor() {
				    public void visit(Klass k) {
				          if (!(k instanceof InstanceKlass)) return;
				          try {
				        	DumpVMClass.dumpKlass((InstanceKlass)k);
				          } catch (Exception e) {
				            System.out.println(k.getName().asString());
				            e.printStackTrace();
				          }
				    }
			    });
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
		    agent.detach();
		}
	}
	
	private static void dumpKlass(InstanceKlass kls) {
		     String klassName = kls.getName().asString();
	         klassName = klassName.replace('/', File.separatorChar);
		     try {
		       OutputStream os = null;
		       if (DumpVMClass.jarStream != null) {
		    	   DumpVMClass.jarStream.putNextEntry(new JarEntry(klassName + ".class"));
		           os = DumpVMClass.jarStream;
		       } else {
			         int index = klassName.lastIndexOf(File.separatorChar);
			         File dir = null;
			         if (index != -1) {
			           String dirName = klassName.substring(0, index);
			           dir = new File(DumpVMClass.outputDirectory, dirName);
			         } else {
			           dir = new File(DumpVMClass.outputDirectory);
			        }
			         dir.mkdirs();
			         File f = new File(dir, klassName.substring(index + 1) + ".class");
			         f.createNewFile();
			         os = new BufferedOutputStream(new FileOutputStream(f));
		       }
		       try {
		         ClassWriter cw = new ClassWriter(kls, os);
		         cw.write();
		       } finally {
		         if (os != DumpVMClass.jarStream)
		           os.close();
		      }
		   }
		   catch (IOException exp) {
		       exp.printStackTrace();
		    }
	   }
}
 

 

 3、先运行DumpClassTest:

[root@oem-ci3bcm02f1h bin]# javac DumpClassTest.java 
[root@oem-ci3bcm02f1h bin]# java DumpClassTest &     
[5] 14060
[root@oem-ci3bcm02f1h bin]#
 4、获得PID 14060 后运行 DumpVMClass:

 

[root@oem-ci3bcm02f1h bin]# javac -cp .:../lib/sa-jdi.jar DumpVMClass.java
[root@oem-ci3bcm02f1h bin]# java -cp .:../lib/sa-jdi.jar DumpVMClass 14060
[root@oem-ci3bcm02f1h bin]#

 

5、运行完就可以看到:

/home/tools/jdk1.6.0_43/class/ 目录下该JVM 14060进程 的class文件都被dump出来了。

 

注:

    以上DumpVMClass 代码大部分来自于sa-jdi.jar 的

sun.jvm.hotspot.tools.jcore.ClassDump

 

你可能感兴趣的:(HotSpot,agent,SA,Serviceability,sa-jdi.jar)