5 Replies Latest reply on Jun 27, 2012 5:44 AM by adinn

    Caught ReturnException: Why?

    benjamin-bin-shen

      Hi,

       

      i am trying Byteman to manipultate a method logic

       

      RULE RuleManipulateSomeCustomersInService

      CLASS CustomerServiceImpl

      METHOD _getCustomersByName(String)

      AT ENTRY

      BIND

        service = $0,

        cus = $1,

        res = service._getCustomersByNameInAnyCase(cus)

      IF cus.matches("^[o-sO-S].*")

      DO

        traceln(">>BM>> entering matches: " + cus),

        RETURN res

      ENDRULE

       

      the class CustomerServiceImpl implements a web service interface generated by Apache CXF from a WSDL, while

      the class Customer from XSD. 

       

      both involved methods are as follows

       

      public List<Customer> getCustomersByName(String name) throws NoSuchCustomerException, ProcessingTimeoutException {

      ...

      }

      private List<Customer> _getCustomersByNameInAnyCase(String name){

                final Customer cust = new Customer();

                cust.setName(name);

                cust.getAddress().add("");

                cust.setBirthDate(GregorianCalendar.getInstance().getTime());

                cust.setNumOrders(1);

                cust.setRevenue(10000);

                cust.setTest(new BigDecimal(1.5));

                cust.setType(CustomerType.BUSINESS);

                return Arrays.asList(new Customer[] {cust});

      }

       

      actually the test results are what i want. however the rule action states "caught ReturnException" with activated option

       

      -Dorg.jboss.byteman.verbose

       

      C[Peter] 2012-06-19 18:20:19,194 [DefaultMessageListenerContainer-34] - >> customer [Peter]

      C[Peter] 2012-06-19 18:20:19,195 [pool-2-thread-2] - == some bla bla, but important debug infos

      Rule.execute called for RuleManipulateSomeCustomersInService_0

      RuleManipulateSomeCustomersInService execute

      >>BM>> entering matches: Peter

      caught ReturnException

      C[Peter] 2012-06-19 18:20:19,197 [DefaultMessageListenerContainer-34] - << found customer [Peter]

       

      i see no reason for the ReturnException since the method called in the trigger action has exactly the same return type as the triggering method.

      would you kindly give an explanation? thx in advance!

       

      BRs, Bin

       

       



        • 1. Re: Caught ReturnException: Why?
          adinn

          Hi,

          Bin Shen wrote:

           

          . . .

          i see no reason for the ReturnException since the method called in the trigger action has exactly the same return type as the triggering method.

          would you kindly give an explanation? thx in advance!

           

          The ReturnException is part of the mechanism Byteman uses to implement an early return from the trigger method. When a RETURN statement in a rule action is executed a ReturnException is thrown. The trigger method is transformed to include a handler which catches the ReturnException and returns form the triger method. If the method is non-void then the injected code retrieves the return value from the exception.

           

          You don't normally see any of this mechanism. However, when Byteman is run in verbose mode the injected handler code includes a print call to trace the catch and that is the message you are seeing. A similar trace statement is injected into the handlers for ThrowException (used to implement THROW) and ExecuteException (used to abort rule execution when the rule actions generate an unexpected exception -- or a TypeException if a type check failure occurs when the rule is type checked at the first triggering).

          • 2. Re: Caught ReturnException: Why?
            benjamin-bin-shen

            Hi, Andrew,

             

            many thx for yr very quick explanation! really appreciate!

             

            BRs, Bin

            • 3. Re: Caught ReturnException: Why?
              adinn

              Hi Bin,

              Bin Shen wrote:

               

              many thx for yr very quick explanation! really appreciate!

               

              No problem. I hope Byteman is making it easier for you to implement your tests. Please let me know if you are finding it difficult to implement something you need or can think of a better way for Byteman to do help you do what you want. I'll always happy to find ways to improve Byteman.

               

              regards,

               

               

              Andrew Dinn

              • 4. Re: Caught ReturnException: Why?
                benjamin-bin-shen

                Hi, Andrew,

                 

                firstly thank you again. Byteman is promising!

                 

                earlier I have tried BTrace (http://kenai.com/projects/btrace/) and YouDebug (http://youdebug.kenai.com/). I think Byteman is the best of the breed.

                 

                IMHO the killer function is non-interactive tracing, debugging and manipulation of production systems. support of JUnit tests is nice, but you can reach the same via mocking.

                 

                i have to accustom myself to the ECA rules. anyway this is acceptable. in this regard it is more confortable to use Java (in case of BTrace) or Groovy (YouDebug).

                 

                rgd. BM Rule Language:

                • CLASS or METHOD part: more stronger support for wild cards or regular expressions?
                • DO part:
                  • calling shared procedures?
                  • creating new Objects? or
                  • support of some control flow?

                 

                for some specific purpose there are some scripts as well as customer helpers to develop. now scripts and the helpers are seperated in two worlds. moreover , the scripts are having no generality. it is very tedious to develop the scripts and helpers from case to case. due to the fact that they are releate to or depend on each other, it would be nice to have some kind of "package", which gets both in one place and gets developed in one Byteman project. with some additional generality we could have encapsulated some best of generic practice, parameterized it and used it "out of the box", hence not invented the wheel every time.

                 

                sorry, Andew, i just write what i, as a new user of Byteman, think spontaneously. forget it if you feel inappropriate. thanks again!

                 

                BRs, Bin

                • 5. Re: Caught ReturnException: Why?
                  adinn

                  Hi Bin,

                   

                  Thanks for your feedback. I'm glad you find Byteman to be an improvement on other tools. It is always appropriate for users to report what they like or dislike about Byteman and also to suggest changes they want to see. I started the project to answer my needs but I will think very hard about your suggestions -- what other users want is critical to the continuing success of Byteman.

                   

                  Bin Shen wrote:

                   

                  i have to accustom myself to the ECA rules. anyway this is acceptable. in this regard it is more confortable to use Java (in case of BTrace) or Groovy (YouDebug).

                   

                  rgd. BM Rule Language:

                  • CLASS or METHOD part: more stronger support for wild cards or regular expressions?
                  • DO part:
                    • calling shared procedures?
                    • creating new Objects? or
                    • support of some control flow?

                  These are interesting ideas and I have thought about implementing them before. I have not decided against them (and of course anyone is free to provide an implementation of them if they want) but I have found good reasons not to do anything about them so far.

                   

                  I have to admit that the main reason for using ECA rules and limiting control flow to a single IF is that it made it much easier to implement the rule parser, type checker, execution engine and compiler. I probably should have done more work at the start and made it possible to inject Java code which used some of the language features you describe but I think that would have have meant that I would never have got the project started.

                   

                  The hardest thing to implement is type checking/type inference and that gets much more complex if you allow more Java code in the scripts, especially the type inference. I could just drop type inference but it is important for a couple of reasons. Firstly, it means rules don't have to be include declarations which keeps simple rules simple. Secondly, it also means that references to state in the trigger method are dynamically typed rather than lexically typed in the rules. This is important when a rule has to apply to more than one trigger method e.g if it is injected into Foo.myMethod(Foo) and Foo.myMethod(Bar, Foo). So, it may be possible to allow more complex code in rule actions but I would have to think very hard about how to do it.

                   

                  As a work-aroudnd it is always an option to wrap up the complex logic in a helper method. This approach also ensures that rule code is simple and clear. So, although it would be nice to be able to support more complex control flow it is not absolutely necessary.

                   

                  I have thought about providing wild cards in CLASS/METHOD clauses and avoided it for performance reasons. The problem is that whenever a class is loaded (or redefined) the Transformer has to decide whether or not to inject a rule into it. That happens for every class that gets loaded (not just the ones mentioned in your rules). So, being able to identify quickly whether a class has a ruel which applies ot it is critical to the performance of the JVM.

                   

                  At present when a class is passed to the transformer it can check very quickly to see if there is a rule which might apply to it because rules arre indexed under the class name with and without package prefix. If you don't load rules which use overriding injection (CLASS ^Foo) or interface rules (INTERFACE Foo) then two simple hash lookups are all that is needed. The cost is nomrally so small as to be unmeasurable. If you do use overriding injection or interface rules then the number of hash lookups is multiplied by the length of the super chain for the class under consideration and/or the number of interfaces implemented by the class. That's still quite a small cost but it can end up adding a single figure % to execution time. Using wild cards in CLASS?INTERFACE clauses would mean that every hash lookup for a class also requires a regex match. That's probably going to add a lot of overhead.

                   

                  The problem is worse if you allow wild cards in METHOD clauses and much, much worse if you use them in combination. Identifying a trigger METHOD match requires Byteman to scan the bytecode for the target class. If you use a very general pattern for the CLASS (e.g. org.my.* or even worse *) and rely on a method name or method pattern to do the filtering then that means you will be scanning bytecode for a lot of classes. Now the scan has been optimised to avoid cases where there is a false match. A quick scan is done to see if there is a method with a matching name/signature. A second detailed scan does a full check and also transforms the method code if needed. So, using a method wild card makes the quick preliminary scan much slower. Using a class wild card makes scans happen more often. So,  there is potential for a lot of wasted time if wild cards are introduced.

                   

                  Of course, these costs could be avoided (or reduced to a very small extra overhead) when no wild-card rules are loaded. So, it is possible to provide this for those who want/need it and can live with the slowdown it will impose without causing much of a problem for those who don't need it. However, there is also a workaround which makes it questionable whether it is worth providing wild cards. As an example, take a look at the dtest package in the contrib directory. You will see that it generates trace rules for all methods of a class or all clases in a package then uses the Submit class to inject them into a program under test. Now dtest is built to inject into a remote server but the same sort of technique can be used to generate and install rules within the local JVM e.g. from test code in a JUnit test. Generating and loading  a set of rules each of which applies to a specific class and method will retain the performance of a (two) simple hash lookup(s)  while still allowing you to inject code across a large code base. So, rather than providing wild cards, I think it might be more profitable to work on providing a variant of dtest which does what you want.

                   

                  Bin Shen wrote:

                   

                  for some specific purpose there are some scripts as well as customer helpers to develop. now scripts and the helpers are seperated in two worlds. moreover , the scripts are having no generality. it is very tedious to develop the scripts and helpers from case to case. due to the fact that they are releate to or depend on each other, it would be nice to have some kind of "package", which gets both in one place and gets developed in one Byteman project. with some additional generality we could have encapsulated some best of generic practice, parameterized it and used it "out of the box", hence not invented the wheel every time.

                   

                  Yes, I agree,  scripts are often verbose and have no great generality and are only loosely tied to their helper code. Better tooling woud help with this problem. In fact, a couple of people have built prototype Eclipse and Idea Byteman plug-ins which make it easier to manage rules and helper code but neither has been fully completed. However, I think some better way of organising/managing the scripts and helpers might improve things enormously, as also woulda library of commmon scripts and helpers. Of course, if you have anything you want to contribute I wold be happy to review it and consider adding it to the contrib or samples directories :-) Anyway, I'll add this as a task for future releases.

                   

                  Bin Shen wrote:

                   

                  sorry, Andew, i just write what i, as a new user of Byteman, think spontaneously. forget it if you feel inappropriate. thanks again!

                   

                  Your comments are very appropriate and very interesting to hear. I hope my expanations help you understand why these features are not yet present. Maybe also they might encourage someone else to look at the problem and contribute ideas for a better solution or even an implementation. Thanks very much for your imput.

                   

                  regards,

                   

                   

                  Andrew Dinn