简体   繁体   English

如何从JVM获取有关加载哪些类以及所有已加载类的规范的信息?

[英]How can I get information from JVM about what classes are loaded along with the specs of all the loaded class?

I want to get the information of all the classes loaded, as well as specs of the classes , such as what methods and their signature, what kind of exceptions can a method throw. 我想获取所有加载的类的信息, 以及类的规范 ,例如什么方法和它们的签名,方法可以抛出什么样的异常。 etc. I know there are previous posts saying how to get all the classes loaded, but not other detailed information, so is there any available thing already to get what I want? 我知道有先前的帖子说如何加载所有类,但没有其他详细信息,所以有没有可用的东西来获得我想要的东西?

As others have mentioned elsewhere, you can do this by attaching an agent to the JVM, as that is the only place the JVM will report on what classes are loaded. 正如其他人在其他地方提到的那样,您可以通过将代理附加到JVM来实现此目的,因为这是JVM将报告加载哪些类的唯一位置。

This class shows how that is done: 这个课程展示了如何完成:

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

public class ClassReporter implements Runnable {
    /** Output file */
    File output;

    /** The JVM instrumentation */
    Instrumentation instrument;

    /** Already reported classes */
    Set<Class<?>> known = new HashSet<Class<?>>();

    /** Is reporter still running? */
    volatile boolean running = true;


    @Override
    public void run() {
        System.out.println("Class Reporter agent running");
        while( running ) {
            if (!report()) return;
            try {
                Thread.sleep(5000);
            } catch (InterruptedException ie) {
                ie.printStackTrace();
                return;
            }
        }
    }


    /**
     * Update the report of loaded classes
     * 
     * @return true if report was written OK
     */
    public synchronized boolean report() {
        Set<Class<?>> report = new HashSet<Class<?>>();
        Class<?>[] classes = instrument.getAllLoadedClasses();
        for(Class<?> c:classes) {
            if (known.add(c)) report.add(c);
        }
        if (report.isEmpty()) return true;

        boolean ret = true;
        FileWriter fw = null;
        try {
            fw = new FileWriter(output, true);
            for(Class<?> c:classes) {
                fw.write(c.getName());
                fw.write('\n');

                for(Method m:c.getDeclaredMethods()) {
                    fw.write(m.toGenericString());
                    fw.write('\n');
                }
                fw.write('\n');
                fw.write('\n');
                fw.flush();
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
            ret = false;
        } finally {
            if (fw != null) {
                try {
                    fw.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                    ret = false;
                }
            }
        }
        return ret;
    }


    /**
     * Initialize the reporter
     * 
     * @param agentArgs
     *            the output file name
     * @param inst
     *            the instrumentation
     */
    public static void premain(String agentArgs, Instrumentation inst) {
        final ClassReporter cr = new ClassReporter();
        cr.instrument = inst;
        File out = new File(agentArgs);
        out.delete();
        try {
            out.createNewFile();
        } catch (IOException ioe) {
            System.out.println("Class Reporter could not create file "
                    + out.getAbsolutePath());
            return;
        }
        cr.output = out;

        Thread thread = new Thread(cr);
        thread.setDaemon(true);
        thread.start();

        Thread shutdown = new Thread() {
            public void run() {
                System.out.println("Class Reporter writing final report");
                cr.running = false;
                cr.report();
                System.out.println("Class Reporter done");
            }
        };

        Runtime.getRuntime().addShutdownHook(shutdown);
    }
}

To turn the class into an agent, you need to package it specially in a JAR file with an appropriate Manifest. 要将类转换为代理,您需要将其特别打包在具有适当Manifest的JAR文件中。 The Manifest is: 清单是:

Premain-Class: ClassReporter

You then create the agent jar with this command: 然后使用以下命令创建代理jar:

jar cvfm cr.jar Manifest.mf ClassReporter*.class

and then to actually use it, you run the application specifying the agent on the command-line like this: 然后实际使用它,你运行应用程序在命令行上指定代理,如下所示:

java -javaagent:cr.jar=cr.txt ActualProgramMainClass

The "cr.txt" is the output file generated. “cr.txt”是生成的输出文件。 You will see output on System.out saying the reporter is running. 你会看到System.out上的输出说记者正在运行。 The output file shows all the information you mention in your question. 输出文件显示您在问题中提到的所有信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM