के माध्यम से बाइटकोड में कोशिश/पकड़ ब्लॉक जोड़ना मैं एएसएम के लिए नया हूं और मुझे बाइटकोड परिवर्तन से संबंधित कुछ मदद चाहिए।एएसएम
प्रश्न: मैं एएसएम के माध्यम से बाइटकोड में पूरी विधि के लिए प्रयास/पकड़ ब्लॉक जोड़ना चाहता हूं और जावा-नॉवरिफ़ विकल्प का उपयोग करके विधि को चलाने के लिए चाहता हूं। मैं पूरी विधि के लिए कोशिश/पकड़ ब्लॉक जोड़ने में सक्षम हो सकता हूं लेकिन जब मैंने विधि को निष्पादित करने का प्रयास किया तो मुझे 'java.lang.VerifyError' मिल रहा है। अगर मैं जावा-नॉवरिफा विकल्प का उपयोग करता हूं तो यह चलाएगा। क्रिप्या मेरि सहायता करे।
नीचे विवरण हैं।
public class Example {
public static void hello() {
System.out.println("Hello world");
}
}
मैं उपरोक्त कोड को एएसएम बाइटकोड उपकरण के साथ प्रयास/पकड़ ब्लॉक को शुरू करने के रूप में नीचे परिवर्तित करना चाहता हूं।
public class Example {
public static void hello() {
try
{
System.out.println("Hello world");
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
कोड के नीचे कोड को जोड़ने/पकड़ने के लिए जोड़ें लेकिन जावा-नोवरिफ़ विकल्प के साथ कोड निष्पादित करने में विफल रहता है।
public class InstrumentExample {
/**
* Our custom method modifier method visitor class. It delegate all calls to
* the super class. Do our logic of adding try/catch block
*
*/
public static class ModifierMethodWriter extends MethodVisitor {
// methodName to make sure adding try catch block for the specific
// method.
private String methodName;
// below label variables are for adding try/catch blocks in instrumented
// code.
private Label lTryBlockStart;
private Label lTryBlockEnd;
private Label lCatchBlockStart;
private Label lCatchBlockEnd;
/**
* constructor for accepting methodVisitor object and methodName
*
* @param api: the ASM API version implemented by this visitor
* @param mv: MethodVisitor obj
* @param methodName : methodName to make sure adding try catch block for the specific method.
*/
public ModifierMethodWriter(int api, MethodVisitor mv, String methodName) {
super(api, mv);
this.methodName = methodName;
}
// We want to add try/catch block for the entire code in the method
// so adding the try/catch when the method is started visiting the code.
@Override
public void visitCode() {
super.visitCode();
// adding try/catch block only if the method is hello()
if (methodName.equals("hello")) {
lTryBlockStart = new Label();
lTryBlockEnd = new Label();
lCatchBlockStart = new Label();
lCatchBlockEnd = new Label();
// set up try-catch block for RuntimeException
visitTryCatchBlock(lTryBlockStart, lTryBlockEnd,
lCatchBlockStart, "java/lang/Exception");
// started the try block
visitLabel(lTryBlockStart);
}
}
@Override
public void visitMaxs(int maxStack, int maxLocals) {
// closing the try block and opening the catch block if the method
// is hello()
if (methodName.equals("hello")) {
// closing the try block
visitLabel(lTryBlockEnd);
// when here, no exception was thrown, so skip exception handler
visitJumpInsn(GOTO, lCatchBlockEnd);
// exception handler starts here, with RuntimeException stored
// on stack
visitLabel(lCatchBlockStart);
// store the RuntimeException in local variable
visitVarInsn(ASTORE, 2);
// here we could for example do e.printStackTrace()
visitVarInsn(ALOAD, 2); // load it
visitMethodInsn(INVOKEVIRTUAL, "java/lang/Exception",
"printStackTrace", "()V", false);
// exception handler ends here:
visitLabel(lCatchBlockEnd);
}
super.visitMaxs(maxStack, maxLocals);
}
}
/**
* Our class modifier class visitor. It delegate all calls to the super
* class Only makes sure that it returns our MethodVisitor for every method
*
*/
public static class ModifierClassWriter extends ClassVisitor {
private int api;
public ModifierClassWriter(int api, ClassWriter cv) {
super(api, cv);
this.api = api;
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature,
exceptions);
// Our custom MethodWriter
ModifierMethodWriter mvw = new ModifierMethodWriter(api, mv, name);
return mvw;
}
}
public static void main(String[] args) throws IOException {
DataOutputStream dout = null;
try {
// loading the class
InputStream in = InstrumentExample.class
.getResourceAsStream("Example.class");
ClassReader classReader = new ClassReader(in);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
// Wrap the ClassWriter with our custom ClassVisitor
ModifierClassWriter mcw = new ModifierClassWriter(ASM4, cw);
ClassVisitor cv = new CheckClassAdapter(mcw);
classReader.accept(cv, 0);
byte[] byteArray = cw.toByteArray();
dout = new DataOutputStream(new FileOutputStream(new File("Example.class")));
dout.write(byteArray);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (dout != null)
dout.close();
}
}
}
डीबगिंग के लिए मैंने चेक क्लास एडाप्टर का उपयोग किया है और मुझे सत्यापन समस्या से नीचे मिला है।
Message:org.objectweb.asm.tree.analysis.AnalyzerException: Execution can fall off end of the code
at org.objectweb.asm.tree.analysis.Analyzer.findSubroutine(Unknown Source)
at org.objectweb.asm.tree.analysis.Analyzer.findSubroutine(Unknown Source)
at org.objectweb.asm.tree.analysis.Analyzer.analyze(Unknown Source)
at org.objectweb.asm.util.CheckClassAdapter.verify(Unknown Source)
at org.objectweb.asm.util.CheckClassAdapter.verify(Unknown Source)
at com.mfr.instrumentation.selenium.work.InstrumentExample.main(InstrumentExample.java:166)
hello()V
00000 ? : L0
00001 ? : GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
00002 ? : LDC "Hello world"
00003 ? : INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
00004 ? : RETURN
00005 ? : L1
00006 ? : GOTO L2
00007 ? : L3
00008 ? : ASTORE 2
00009 ? : ALOAD 2
00010 ? : INVOKEVIRTUAL java/lang/Exception.printStackTrace()V
00011 ? : L2
TRYCATCHBLOCK L0 L1 L3 java/lang/Exception
मैं उपरोक्त सत्यापन संदेश को समझने में विफल रहा।
सवाल क्या है? – biziclop
प्रश्न यह है कि मैं अपने प्रारंभिक कोड को एएसएम बाइटकोड इंस्ट्रूमेंटेशन का उपयोग करके कोशिश/पकड़ने वाले ब्लॉक को अपने बाद वाले कोड में आउट/कैच ब्लॉक के साथ कैसे बदल सकता हूं। –