Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

pitfalls.adoc 2.3KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. = Pitfalls
  2. [[pitfalls-intro]]
  3. == Introduction
  4. This chapter consists of a few AspectJ programs that may lead to
  5. surprising behavior and how to understand them.
  6. [[pitfalls-infiniteLoops]]
  7. == Infinite loops
  8. Here is a Java program with peculiar behavior
  9. [source, java]
  10. ....
  11. public class Main {
  12. public static void main(String[] args) {
  13. foo();
  14. System.out.println("done with call to foo");
  15. }
  16. static void foo() {
  17. try {
  18. foo();
  19. } finally {
  20. foo();
  21. }
  22. }
  23. }
  24. ....
  25. This program will never reach the `println` call, but when it aborts may
  26. have no stack trace.
  27. This silence is caused by multiple ``StackOverflowException``s. First the
  28. infinite loop in the body of the method generates one, which the finally
  29. clause tries to handle. But this finally clause also generates an
  30. infinite loop which the current JVMs can't handle gracefully leading to
  31. the completely silent abort.
  32. The following short aspect will also generate this behavior:
  33. [source, java]
  34. ....
  35. aspect A {
  36. before(): call(* *(..)) { System.out.println("before"); }
  37. after(): call(* *(..)) { System.out.println("after"); }
  38. }
  39. ....
  40. Why? Because the call to println is also a call matched by the pointcut
  41. `call (* *(..))`. We get no output because we used simple `after()`
  42. advice. If the aspect were changed to
  43. [source, java]
  44. ....
  45. aspect A {
  46. before(): call(* *(..)) { System.out.println("before"); }
  47. after() returning: call(* *(..)) { System.out.println("after"); }
  48. }
  49. ....
  50. then at least a `StackOverflowException` with a stack trace would be seen.
  51. In both cases, though, the overall problem is advice applying within its
  52. own body.
  53. There's a simple idiom to use if you ever have a worry that your advice
  54. might apply in this way. Just restrict the advice from occurring in join
  55. points caused within the aspect. So:
  56. [source, java]
  57. ....
  58. aspect A {
  59. before(): call(* *(..)) && !within(A) { System.out.println("before"); }
  60. after() returning: call(* *(..)) && !within(A) { System.out.println("after"); }
  61. }
  62. ....
  63. Other solutions might be to more closely restrict the pointcut in other
  64. ways, for example:
  65. [source, java]
  66. ....
  67. aspect A {
  68. before(): call(* MyObject.*(..)) { System.out.println("before"); }
  69. after() returning: call(* MyObject.*(..)) { System.out.println("after"); }
  70. }
  71. ....
  72. The moral of the story is that unrestricted generic pointcuts can pick
  73. out more join points than intended.