बाइटकोड का विश्लेषण करने के लिए, मैं ASM की अनुशंसा करता हूं। विश्लेषण करने के लिए कक्षाओं की एक सूची को देखते हुए, एक आगंतुक बनाया जा सकता है जिसमें आपको रुचि रखने वाली विधि कॉल मिलती है। एक कार्यान्वयन जो जार फ़ाइल में कक्षाओं का विश्लेषण करता है, नीचे है।
ध्यान दें कि एएसएम internalNames का उपयोग '/' के बजाय '/' के साथ करता है। एक विभाजक के रूप में। संशोधक के बिना standard declaration के रूप में लक्ष्य विधि निर्दिष्ट करें।
java -cp "classes;asm-3.1.jar;asm-commons-3.1.jar" App \
c:/java/jdk/jre/lib/rt.jar \
java/io/PrintStream "void println(String)"
संपादित: स्रोत और लाइन नंबर कहा: नोट: यह है कि
उदाहरण के लिए, तरीकों कि System.out.println बुला जा सकता है ("foo") जावा रनटाइम जार में सूचीबद्ध करने के लिए केवल कॉलिंग विधि के अंतिम लक्ष्य विधि आमंत्रण को इंगित करता है - मूल क्यू केवल जानना चाहता था जो विधियां। मैं इसे पाठक के लिए कॉलिंग विधि घोषणा की लाइन संख्या दिखाने के लिए, या प्रत्येक लक्ष्य आमंत्रण की रेखा संख्या दिखाने के लिए एक अभ्यास के रूप में छोड़ देता हूं, जो वास्तव में आप वास्तव में क्या कर रहे हैं उसके आधार पर। :) में
परिणाम:
LogSupport.java:44 com/sun/activation/registries/LogSupport log (Ljava/lang/String;)V
LogSupport.java:50 com/sun/activation/registries/LogSupport log (Ljava/lang/String;Ljava/lang/Throwable;)V
...
Throwable.java:498 java/lang/Throwable printStackTraceAsCause (Ljava/io/PrintStream;[Ljava/lang/StackTraceElement;)V
--
885 methods invoke java/io/PrintStream println (Ljava/lang/String;)V
स्रोत:
public class App {
private String targetClass;
private Method targetMethod;
private AppClassVisitor cv;
private ArrayList<Callee> callees = new ArrayList<Callee>();
private static class Callee {
String className;
String methodName;
String methodDesc;
String source;
int line;
public Callee(String cName, String mName, String mDesc, String src, int ln) {
className = cName; methodName = mName; methodDesc = mDesc; source = src; line = ln;
}
}
private class AppMethodVisitor extends MethodAdapter {
boolean callsTarget;
int line;
public AppMethodVisitor() { super(new EmptyVisitor()); }
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
if (owner.equals(targetClass)
&& name.equals(targetMethod.getName())
&& desc.equals(targetMethod.getDescriptor())) {
callsTarget = true;
}
}
public void visitCode() {
callsTarget = false;
}
public void visitLineNumber(int line, Label start) {
this.line = line;
}
public void visitEnd() {
if (callsTarget)
callees.add(new Callee(cv.className, cv.methodName, cv.methodDesc,
cv.source, line));
}
}
private class AppClassVisitor extends ClassAdapter {
private AppMethodVisitor mv = new AppMethodVisitor();
public String source;
public String className;
public String methodName;
public String methodDesc;
public AppClassVisitor() { super(new EmptyVisitor()); }
public void visit(int version, int access, String name,
String signature, String superName, String[] interfaces) {
className = name;
}
public void visitSource(String source, String debug) {
this.source = source;
}
public MethodVisitor visitMethod(int access, String name,
String desc, String signature,
String[] exceptions) {
methodName = name;
methodDesc = desc;
return mv;
}
}
public void findCallingMethodsInJar(String jarPath, String targetClass,
String targetMethodDeclaration) throws Exception {
this.targetClass = targetClass;
this.targetMethod = Method.getMethod(targetMethodDeclaration);
this.cv = new AppClassVisitor();
JarFile jarFile = new JarFile(jarPath);
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (entry.getName().endsWith(".class")) {
InputStream stream = new BufferedInputStream(jarFile.getInputStream(entry), 1024);
ClassReader reader = new ClassReader(stream);
reader.accept(cv, 0);
stream.close();
}
}
}
public static void main(String[] args) {
try {
App app = new App();
app.findCallingMethodsInJar(args[0], args[1], args[2]);
for (Callee c : app.callees) {
System.out.println(c.source+":"+c.line+" "+c.className+" "+c.methodName+" "+c.methodDesc);
}
System.out.println("--\n"+app.callees.size()+" methods invoke "+
app.targetClass+" "+
app.targetMethod.getName()+" "+app.targetMethod.getDescriptor());
} catch(Exception x) {
x.printStackTrace();
}
}
}
दोस्तों मिक्लोसर ने क्यू संपादित किया और कहा कि यह रनटाइम पर होने की आवश्यकता है, वहां अनगिनत लोग दिखाई देते हैं कि यह आईडीई में कैसे किया जाए। ऊपर वोट @ चाडविक –
शायद आप समझा सकते हैं कि आपको रनटाइम पर ऐसा करने की आवश्यकता क्यों है क्योंकि लोग इस आवश्यकता में नहीं आ सकते हैं। –