Community
Participate
Working Groups
The AspectJ compiler output for the following test program produces a verify error on a Sun 1.3.1_15-b01, a Sun 1.4.2_05-b04 VM and a Sun 1.5.0_02-b09 VM. It does not produce this error on a JRockIt 1.5.0_02 VM. Compiling with the 1.2.1, the 1.5.0 M2 and the July 15 CVS HEAD AspectJ compiler all produce the error. Exception in thread "main" java.lang.VerifyError: (class: domain/instance/Concre te, method: key_aroundBody0 signature: (Ldomain/instance/Concrete;Ldomain/instan ce/Intermediate;Ljava/lang/Object;)V) Bad access to protected data package domain; import java.util.Collections; import java.util.List; public aspect WrapCollection { void around(List list) : set(* *.*) && target(Base+) && args(list) { proceed(Collections.unmodifiableList(list)); } } package domain; public abstract class Base { protected Object key; } package domain.instance; public class Concrete extends Intermediate { public Concrete() { } public Concrete(String key) { super.key = key; } public static void main(String args[]) { new Concrete(); } } package domain.instance; import domain.Base; public abstract class Intermediate extends Base { }
for M4
Background material for this bug can be found in JLS section 6.6.7. Here are two classes: package a; public class Top { protected int x,y; } package b; import a.*; public class Bottom extends Top { public void m(Top t) { t.x = 1; t.y = 2; } public void n(Bottom b) { b.x = 1; b.y = 2; } } If you try to compile these two classes, you will get: Bottom.java:8: x has protected access in a.Top t.x = 1; ^ Bottom.java:9: y has protected access in a.Top t.y = 2; ^ 2 errors i.e. the references to the protected fields of a Top instance in m() are not allowed. The reason is that although Bottom *is* a subclass of Top, it is not involved in the implementation of Top, which means the method m() which takes a Top instance can't arbitrarily fiddle with its protected fields. Method n() takes a Bottom and can access the protected fields in its supertype. In the original failing program, the around advice we create suffers exactly the same problem, the generated aroundBody method looks like this: private static final void key_aroundBody0(Concrete concrete, Intermediate intermediate, Object obj) { intermediate.key = obj; } and is created in the Concrete class. key is a protected field in Base and so cannot be accessed through the parameter of type Intermediate. If we modify the ctor in Concrete, from public Concrete(String key) { super.key = key; } to public Concrete(String key) { this.key = key; } then recompile, the new aroundBody code is: private static final void key_aroundBody0(Concrete concrete, Concrete concrete1, Object obj) { concrete1.key = obj; } and it works fine - because the type through which we are referring to key is 'Concrete'.
we're not going to get to this for 1.5.0 - moving to 1.5.1. It's been very seldom seen in the wild and there is no straightforward fix.
Although ironically this bug was encountered in the wild when adding aspects to an existing project...