Bug 347395 - java.lang.VerifyError after custom aspect weaving
Summary: java.lang.VerifyError after custom aspect weaving
Status: NEW
Alias: None
Product: AspectJ
Classification: Tools
Component: LTWeaving (show other bugs)
Version: 1.6.11   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-05-27 02:00 EDT by akankaluga CLA
Modified: 2011-06-20 13:22 EDT (History)
1 user (show)

See Also:


Attachments
Initial aspect class (8.42 KB, application/octet-stream)
2011-05-28 03:03 EDT, akankaluga CLA
no flags Details
Decompiled woven TaskHistoryAspect (13.42 KB, application/octet-stream)
2011-05-28 03:06 EDT, akankaluga CLA
no flags Details
updated decompiled aspect (13.00 KB, application/octet-stream)
2011-05-28 03:19 EDT, akankaluga CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description akankaluga CLA 2011-05-27 02:00:44 EDT
Build Identifier: 

I was updated to new version of aspectj (1.6.11) from ver 1.6.0. My aspect is looking like:
@Aspect
public class TaskHistoryAspect {

    @Pointcut("execution(@xxx.TaskModification * *.*(..))")
    void modification(ProceedingJoinPoint joinPoint) {}

    @Around("modification(joinPoint)")
    public Object aroundModification(ProceedingJoinPoint joinPoint) throws Throwable {
        Object target = joinPoint.getTarget();
        Task task = ...// obtaining from args
        List<Task> list = ... // obtaining from args;
        try {
            Object result = joinPoint.proceed(joinPoint.getArgs());
            if (task != null) {
                logModification(joinPoint, task);
            } else if (list != null) {
                logModification(joinPoint, list);
            }
            return result;
        } finally {
           // do somthing
        }
    }

    private void logModification(JoinPoint joinPoint, Task task) {
        // log for task
    }

    private void logModification(JoinPoint joinPoint, List<Task> tasks) {
       // log for each task in list
    }
}

Part of code was skipped for simplifying.
After weaving that aspect (I use LTW) was an error:

Caused by: java.lang.VerifyError: (class: xxx/TaskHistoryAspect, method: aroundModification signature: (Lorg/aspectj/lang/ProceedingJoinPoint;)Ljava/lang/Object;) Incompatible argument to function

I have saved weaved code for class, it seems like (also simplified):
@Around(value="modification(joinPoint)")
    public Object aroundModification(ProceedingJoinPoint joinPoint)
        throws Throwable
    {
        Task task;
        List list;
...
        Object obj;
        Object result = joinPoint.proceed(joinPoint.getArgs());
        if(task != null)
            ajc$inlineAccessMethod$xxx_TaskHistoryAspect$xxx_TaskHistoryAspect$logModification(this, joinPoint, task);
        else
        if(list != null)
            ajc$inlineAccessMethod$xxx_TaskHistoryAspect$xxx_TaskHistoryAspect$logModification(this, joinPoint, list);
        obj = result;
 ...
    }

and only 1 method with name ajc$inlineAccessMethod$xxx_TaskHistoryAspect$xxx_TaskHistoryAspect$logModification with Task argument (for List was not presented):

public static void ajc$inlineAccessMethod$xxx_TaskHistoryAspect$xxx_TaskHistoryAspect$logModification(TaskHistoryAspect taskhistoryaspect, JoinPoint joinpoint, Task task)
    {
        taskhistoryaspect.logModification(joinpoint, task);
    }

I think, the problem cause is incorrect class transformation when there are overloaded methods. It is only hypothesis..


Reproducible: Always
Comment 1 Andrew Clement CLA 2011-05-27 12:25:31 EDT
is there anyway you can complete the sample with something that gets advised and shows the failure when executing?  I tried creating something simple but it just worked for me.
Comment 2 akankaluga CLA 2011-05-28 03:03:56 EDT
Created attachment 196820 [details]
Initial aspect class

TaskHistoryAspect, initial aspect class
Comment 3 akankaluga CLA 2011-05-28 03:06:21 EDT
Created attachment 196821 [details]
Decompiled woven TaskHistoryAspect

I had saved transformed TaskHistoryAspect class (in debug during class loading by TomcatInstrumentalClassloader) and decompiled it later. Decompiled class is in attachement
Comment 4 akankaluga CLA 2011-05-28 03:12:27 EDT
I have attached initial and woven aspects (in files was changed only package, to xxx). Also I have noticed that there is join point from another aspect (ExceptionsTranslationAspect) in method public TaskAuditService getTaskAuditService(). It is strange... I can provide code for ExceptionsTranslationAspect too if needed.
Comment 5 akankaluga CLA 2011-05-28 03:19:57 EDT
Created attachment 196822 [details]
updated decompiled aspect

updated
Comment 6 akankaluga CLA 2011-05-28 03:24:42 EDT
After changing aspect code to new (see below) all things become well.

@Around("modification(joinPoint)")
    public Object aroundModification(ProceedingJoinPoint joinPoint) throws Throwable {
        Object target = joinPoint.getTarget();
        List<Task> list = new LinkedList<Task>();
        if (target instanceof TaskAware) {
            list.add(((TaskAware) target).getTask());
        } else {
            for (Object arg : joinPoint.getArgs()) {
                if (arg instanceof Task) {
                    list.add((Task) arg);
                    break;
                } else if(arg instanceof List) {
                    List tmpLst = new LinkedList((List) arg);
                    if (tmpLst.size() > 0 && tmpLst.get(0) instanceof Task) {
                        list.addAll(tmpLst);
                        break;
                    }
                }
            }
        }
        pushInfoForTaskList(list);
        try {
            Object result = joinPoint.proceed(joinPoint.getArgs());
            logModification(joinPoint, list);
            return result;
        } finally {
            popInfoForTaskList(list);
        }
    }
Comment 7 Andrew Clement CLA 2011-06-20 13:22:57 EDT
ok - the problem here is the two similar methods:

    private void logModification(JoinPoint joinPoint, Task task) {
        // log for task
    }

    private void logModification(JoinPoint joinPoint, List<Task> tasks) {
       // log for each task in list
    }

These only differ in terms of parameters.  AspectJ attempts to generate an accessor method for calling these from elsewhere (it needs to because they are private).  Because the parameters aren't used in the logic that computes the accessors, it generates one accessor for both methods (!).  Clearly this accessor can't cope with the two kinds of second parameter (task/list) and so a verify error comes out.  Simplest workaround is renaming one of them (call it logModificationWithList for example).  I have a prototype of the fix but generating two accessors in this situation is breaking some other tests and I still have to get to the bottom of why that is.