[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Re: how to write polymorphic exception throwing

>>I'm stuck on how to write polymorphic around advice that
>> might throw a checked exception of diffent types
>> depending on the signature of the called method. E.g.,

I know Ron knows what he is doing, but wanted to add some
background here for other readers, try to complete
the code a bit, and comment on the generics suggestion.

In Java, compilers are responsible for verifying that
code can only throw declared checked exceptions, to
guarantee that no other checked exceptions will be
thrown from that code.  AspectJ is careful to preserve
this guarantee by requiring at each join point that only
checked exceptions declared in the underlying join point
can be thrown from any advice on that join point.  That's
one of the things that makes AspectJ a safe extension
to Java, and one of the advantages of using the current
compiler/weaver approach over a reflective approach.

So like any other code, advice has to declare any checked
exceptions it throws, and ajc ensures that all join points
are declared to throw that checked exception:

  before() throws IOException : somePointcut() {
     if (blah) throw new IOException("blah");
     ...
  }

If any join points picked out by somePointcut() are
not declared to throw an IOException, then this advice
will cause a compile-time error.

If you modify bytecode to remove the type-checking
required to verify that an exception is unchecked
(a) it's not guaranteed to work in all VM's; and
(b) you should do the work at runtime of verifying
that any checked exception is permitted by the join point.

You can do that work by downcasting Signature to
CodeSignature to get a list of declared exceptions,
and restricting the exceptions thrown accordingly:

  before() : somePointcut() {
     Throwable toThrow = getThrowable(thisJoinPointStaticPart);
     if (null != toThrow) {
        dynamicThrow(toThrow);
     }
     ...
  }

  Throwable getThrowable(JoinPoint.StaticPart sp) {
      Signature sig = sp.getSignature();
      if (sig instanceof CodeSignature) {
          CodeSignature codeSig = (CodeSignature) sig;
          Class[] declaredExceptions = codeSig.getExceptionTypes();
          // use this to verify that generated exception is correct...
      }
  }

(code unvalidated, might have errors)

Now, will generics help?  I don't know, but I don't think
this will work:

>>With Java 1.5 generics it will hopefully be easy to do:
>>    protected void dynamicThrow(T t) throws T [T instanceof Throwable] {
>>        throw t;
>>    }

Nor does this seem useful:

  aspect A<Thrown> {
      before() throws Thrown: Foo.somePointcut() {
          if (blah) throw new Thrown("blah");
      }
  }

.. since aspects are constructed by the runtime system,
and it comes up against another question -- would this
work?:

      before() throws <Thrown>: Foo.somePointcut() {
          if (blah) throw new Thrown("blah");
      }

Probably not - this I believe is impossible:

      void method() throws <Thrown> { ... }

Because generic Java operates by type-erasure, it would
have to generate multiple methods differing only in the
exceptions thrown.  While GJ can use bytecode to implement
parametric result types (See "A bridge too far" in the
GJ tutorial), I wouldn't think it would do the same for
exceptions.  It's possible that an AspectJ implementation
could do this with separate inlines and creative naming
of non-inlined advice, but it seems weird to support a
generic type in AspectJ that's not supported in Java.

However, I'm no expert on generics, I haven't checked this
in the early-access release of generics, and I'm
sure this question has been addressed.  Does anyone know
what the answer is or where it has been discussed?

Wes

Ron Bodkin wrote:

I figured out a way to do this. I used Java assembly code to create a dynamicThrow method that doesn't check its exceptions. If anyone would like the compiled class file let me know.

Here's more detail:

Compiled from DynamicThrow.java
public class ajee.utility.DynamicThrow extends java.lang.Object {
    public ajee.utility.DynamicThrow();
    public static void dynamicThrow(java.lang.Throwable);
}

Method ajee.utility.DynamicThrow()
   0 aload_0
   1 invokespecial #1 <Method java.lang.Object()>
   4 return

Method void dynamicThrow(java.lang.Throwable)
   0 aload_0
   1 athrow

To get this, I wrote:
/*
*
* Created on 30-Jun-2003
*
* Copyright (c) 2003 New Aspects of Security.
* All rights reserved.
*
* Ron Bodkin
*/
package ajee.utility;

/**
 * This class provides a single method, which allows dynamically
 * throwing an exception of any type at runtime.
 * To build it requires bytecode assembly.
 */
public class DynamicThrow {
    /** This method always throws its parameter as an exception.
     * It throws <em>any</em> Throwable without including it in the
     * signature as a checked exception. Useful, e.g., in highly
     * polymorphic around advice.
     */
    public static void dynamicThrow(Throwable throwable) {
        throw (RuntimeException)throwable;
    }
}

then used a BCEL program to remove the CHECKCAST instruction :-) - pretty much their remove NOP peephole optimizer, but just removing CHECKCAST

Ron Bodkin
Chief Technology Officer
New Aspects of Security
m: (415) 509-2895


------------Original Message-------------
From: "Ron Bodkin" <rbodkin@xxxxxxxxxxx>
To: aspectj-users@xxxxxxxxxxx
Date: Sun, Jun-29-2003 9:36 PM
Subject: how to write polymorphic exception throwing

Hi all,

I'm stuck on how to write polymorphic around advice that might throw a checked exception of diffent types depending on the signature of the called method. E.g.,
   void around() : somepcd() {
       if (getThrowable() != null) {
           dynamicThrow(getThrowable());
       }
   }

With Java 1.5 generics it will hopefully be easy to do:
   protected void dynamicThrow(T t) throws T [T instanceof Throwable] {
       throw t;
   }

However, with the current AspectJ and Java it seems like it can't be done. I tried using reflection (code illustrated below) but this just throws an InvocationTargetException caused by the intended exception. Any suggestions of how to do this, or for other ways to accomplish the same goal?

Using reflection (with exception handling omitted):

   void around() : somepcd() {
       if (getThrowable() != null) {
           method = ImposterProcessing.class.getMethod("dynamicThrow", new Class[] { Throwable.class });
           method.invoke(this, new Object[] { getThrowable() });
       }
   }

public void dynamicThrow(Throwable t) throws Throwable {
throw t;
}


Ron

Ron Bodkin
Chief Technology Officer
New Aspects of Security
m: (415) 509-2895


_______________________________________________ aspectj-users mailing list aspectj-users@xxxxxxxxxxx http://dev.eclipse.org/mailman/listinfo/aspectj-users