Skip to main content

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

Wes's email motivated me to verify my expectations about gj. I was able to get the following code to compile & run with the 2.0 adding generics EA release. It produced the expected result "caught ExceptionA". So the good news is that Java 1.5 will allow the kind of type safe polymorphics throws I wanted for my testing framework. Here's the test code:

public class PolyThrow {
   static void foo() throws ExceptionA {
       dynamicThrow(new ExceptionA());
   }
   static void bar() throws ExceptionB {
       dynamicThrow(new ExceptionB());
   }
   static <T extends Throwable> void dynamicThrow(T t) throws T {
    throw t;
   }
   public static void main(String args[]) {
    try {
       foo();
       bar();
    } catch (Throwable t) {
       System.out.println("caught "+t);
    }
   }
}

class ExceptionA extends Exception {}
class ExceptionB extends Exception {}

This works with the javac-novariance version (i.e., excluding experimental features) too.

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

> ------------Original Message-------------
> From: Wes Isberg <wes@xxxxxxxxxxxxxx>
> To: aspectj-users@xxxxxxxxxxx
> Date: Sun, Jul-13-2003 1:15 PM
> Subject: 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
> > 
> 
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> http://dev.eclipse.org/mailman/listinfo/aspectj-users
> 


Back to the top