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?
Asked
Active
Viewed 631 times
0
-
command line parameter for the VM `-verbose:class` shows at least which classes are loaded – MrSmith42 Jan 03 '13 at 23:23
-
2you want this information programmatically from within Java or for instance from a running java process via shell ? (please update the question) – Stefanos Kalantzis Jan 03 '13 at 23:24
-
See this question: http://stackoverflow.com/questions/2548384/java-get-a-list-of-all-classes-loaded-in-the-jvm – Diego Basch Jan 04 '13 at 00:04
1 Answers
2
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.
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. The Manifest is:
Premain-Class: ClassReporter
You then create the agent jar with this command:
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. You will see output on System.out saying the reporter is running. The output file shows all the information you mention in your question.

Simon G.
- 6,587
- 25
- 30