Bug 104249 - Verify Error in 1.2.1, 1.5.0 M2, and HEAD
Summary: Verify Error in 1.2.1, 1.5.0 M2, and HEAD
Status: ASSIGNED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: DEVELOPMENT   Edit
Hardware: PC Windows XP
: P3 major (vote)
Target Milestone: ---   Edit
Assignee: Adrian Colyer CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-07-18 14:26 EDT by Ron Bodkin CLA
Modified: 2006-06-06 17:50 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ron Bodkin CLA 2005-07-18 14:26:51 EDT
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 {
}
Comment 1 Adrian Colyer CLA 2005-08-26 11:38:49 EDT
for M4
Comment 2 Andrew Clement CLA 2005-09-14 04:25:27 EDT
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'.
Comment 3 Adrian Colyer CLA 2005-10-28 06:51:11 EDT
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.
Comment 4 Ron Bodkin CLA 2006-06-06 17:50:50 EDT
Although ironically this bug was encountered in the wild when adding aspects to an existing project...