zoukankan      html  css  js  c++  java
  • BCEL Incompatibile Stack 规格严格

    The problem is that your jsr's into the finally block occur from places that have a different number of
    entries on the stack, and the verifier doesn't support that.

    Either don't implement your finally with a jsr (inline the content directly), or clean up your stack prior to
    the jsr so it's consistent with the other method exit points.

    - Paul

    -----Original Message-----
    From: Vincent Marquez [mailto:vmarquez <at> totemworks.com]
    Sent: Tuesday, December 14, 2004 11:53 AM
    To: bcel-user <at> jakarta.apache.org
    Subject: Try/Catch Errors

    I'm not sure how active the list is, but I'll give it a shot.  I'm
    having trouble adding bytecode to methods wtih try/catch blocks.  I've
    been able to modify them correctly without try/catch blocks, but as soon
    as I uncomment them, I get the following error:

    Exception in thread "main" java.lang.VerifyError: (class: Test, method:
    main signature: ([Ljava/lang/String;)V) Inconsistent stack height 0 != 2

    I am calling setMaxStack() on the MethodGen instance.  I assume there is
    some simple trick that i'm missing?

    Thanks in advance for any help.

    --vince

    =======================================================

    Hi All, 
    	
    	Currently i am planning to instrument each method of a class
    dynamically with system.out.println() statements.
    	
    	as it is not possible to get it executed, due to the return
    statements which are available in middle of method, 
    
    	As seen from many sources, implementing it with try and finally
    is a good idea.
    
    	finally seems to be more complex to handle compared to catch
    (atleast to me).
    
    	however i got the source from internet, i could not understand
    few things in the source, could some one please clarify me.
    
    	i have directly put put my understandings and queries in the
    middle of code IN CAPS, [code is given below, of course not too big]. So
    please correct me and help me in this regard.
    
    Thank you
    Reddy
    
    
    
    public void instrumentMethod (ClassGen cg, MethodGen mg)
    	{
    		InstructionList il = mg.getInstructionList();
    
    		InstructionFactory ifact = new InstructionFactory(cg);
    
    		InstructionHandle start = il.getStart();
    		InstructionHandle end = il.getEnd();
    
    
    		//  IN THE FOLLOWING SNIPPET OF CODE, CALL TO
    SUBROUTINES ARE INSERTED AND ALL THE TARGETS OF RETURN INSTRUCTIONS ARE
    CHANGED
    
    		Collection<JSR> jsrs = new ArrayList<JSR>();
    		for (Iterator i = il.iterator(); i.hasNext(); ) {
    			InstructionHandle ih =
    (InstructionHandle)i.next();
    
    			if (ih.getInstruction() instanceof RETURN) {
    				JSR jsr2 = new JSR(null);
    				jsrs.add(jsr2);
    				InstructionHandle n = il.insert(ih,
    jsr2);
    							
    				il.redirectBranches(ih, n);
    			}
    		}
    
    		// END OF ABOVE UNDERSTANDING. AM I CORRECT ??
    
    		
    		
    		InstructionHandle h1 = il.append(new ASTORE(0)); // AT
    THE CURRENT SITUATION, WHAT IS ON THE TOP OF STACK AND WHY IS IT
    STORED??
    
    		JSR jsr = new JSR(null);
    // WHY A SUBROUTINE CALL IS DONE HERE??? 
    
    		jsrs.add(jsr);
    		il.append(jsr);
    
    		InstructionHandle h2 = il.append(new ALOAD(0));	  //
    REFLECTS THE ABOVE STORE OPERATION; SO WHAT IS ACTUALLY IN THIS NOW??
    
    		il.append(new ATHROW());
    // I THINK IT IS TO RETHROW THE EXCEPTION IF AN EXCEPTION ARISES
    
    		InstructionHandle handler = il.append(new ASTORE(1)); //
    STORES THE EXCEPTION VARIABLE
    
    		// I WILL APPEND AN PRINTLN STATEMENT HERE 
    
    		il.append(new RET(1));
    // RETURNING FROM SUBROUTINE, BUT DOESNT THE INDEX OF RET START AT 0
    
    		for (JSR j : jsrs) {
    			j.setTarget(handler);
    		}	
    
    		mg.addExceptionHandler(start, end, h1, null);	//
    DOESNT THE EXCEPTION HANDLER START AT HANDLE handler(which is just 3
    lines above in this code)
    
    		il.setPositions(true);
    //  IS THIS NECESSARY ??
    	}

    Andrew Huntwork <a...@huntwork.net> 11075517472005年2月5日 5:15:47
    Koduru, Rajendra Kumar Reddy wrote: > // IN THE FOLLOWING SNIPPET OF CODE, CALL TO > SUBROUTINES ARE INSERTED AND ALL THE TARGETS OF RETURN INSTRUCTIONS ARE > CHANGED
    returns are not targeters. what you&apos;re redirecting below are things that target return. you want things that jump directly to the return to jump to the jsr instead. that way the jsr will be executed whenever the return is executed.
    > > Collection<JSR> jsrs = new ArrayList<JSR>(); > for (Iterator i = il.iterator(); i.hasNext(); ) { > InstructionHandle ih = > (InstructionHandle)i.next(); > > if (ih.getInstruction() instanceof RETURN) { > JSR jsr2 = new JSR(null); > jsrs.add(jsr2); > InstructionHandle n = il.insert(ih, > jsr2); > > il.redirectBranches(ih, n); > } > } > > // END OF ABOVE UNDERSTANDING. AM I CORRECT ?? > > > > InstructionHandle h1 = il.append(new ASTORE(0)); // AT > THE CURRENT SITUATION, WHAT IS ON THE TOP OF STACK AND WHY IS IT > STORED??
    you are inserting a try/catch around the entire original function to implement finally. h1 is the handler. an exception handler is executed with the Throwable on the stack, and that&apos;s what you&apos;re storing in lv 0.
    > > JSR jsr = new JSR(null); > // WHY A SUBROUTINE CALL IS DONE HERE???
    the basic idea of finally is that you insert one subroutine that will be executed before the function exits by any path. the possible exit paths are: all of the return instructions and an uncaught exception. we took care of calling the subroutine from the return instructions above. now we&apos;re taking care of exits via uncaught exceptions. this block catches all exceptions, calls the subroutine, and re-throws the exception.
    > > jsrs.add(jsr); > il.append(jsr); > > InstructionHandle h2 = il.append(new ALOAD(0)); // > REFLECTS THE ABOVE STORE OPERATION; SO WHAT IS ACTUALLY IN THIS NOW??
    here we load the exception we caught and stored at the beginning of the block and re-throw it
    > > il.append(new ATHROW()); > // I THINK IT IS TO RETHROW THE EXCEPTION IF AN EXCEPTION ARISES
    yep
    > > InstructionHandle handler = il.append(new ASTORE(1)); // > STORES THE EXCEPTION VARIABLE
    no. a subroutine is executed with the return address on the stack. this is a special jvm type. that&apos;s what we&apos;re storing here.
    > > // I WILL APPEND AN PRINTLN STATEMENT HERE
    good. this is the right place for it.
    > > il.append(new RET(1)); > // RETURNING FROM SUBROUTINE, BUT DOESNT THE INDEX OF RET START AT 0
    the argument to ret is a local variable index containing a return address. Thus, jsr and ret are assymetric. one puts a return address onto the stack, and the other loads it from a local variable. whatever.
    > > for (JSR j : jsrs) { > j.setTarget(handler); > } > > mg.addExceptionHandler(start, end, h1, null); // > DOESNT THE EXCEPTION HANDLER START AT HANDLE handler(which is just 3 > lines above in this code)
    see above re: catching and re-throwing all uncaught exceptions.
    > > il.setPositions(true); > // IS THIS NECESSARY ??
    i don&apos;t know, but just to be safe i&apos;d at least call il.setPositions();
    > } > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: <bcel...@jakarta.apache.org> > For additional commands, e-mail: bcel...@jakarta.apache.org> >

     http://www.geekyarticles.com/2011/08/manipulating-java-class-files-with-bcel_18.html

    总算从两位老外的帖子里面找到答案了,原因就是代码缺少跳转,如果是try,finally注意一下jsr和ret

    如果是try catch 注意一下GOTO,我总结的,BCEL还是不熟悉啊,可能还有别的好方法。

    用BCEL生成代码一看,反编译的代码一样,但是字节码和高手的差距太大,这充分说明编译器好坏重要性,相当于你自己写了一个编译器,

    如果同样的代码,字节码多,肯定效率不是很高,看来还得努力啊。Java水很深啊。

  • 相关阅读:
    C#获取局域网MAC地址
    查看Linux是32位还是64位的方法
    JS判断不能为空实例代码
    SQL2005数据库行列转换
    mysql 导入导出数据库、数据表的方法
    linux kill 关闭进程命令
    设置CentOS控制台分辨率图文详解
    Windows 2003 IIS 不支持ASP问题的解决方法
    稳聘App设计图分享
    Sql 中存储过程详细案例
  • 原文地址:https://www.cnblogs.com/diyunpeng/p/2159024.html
Copyright © 2011-2022 走看看