Bug 323507 - NoClassDefFoundError is risen after compiling with AspectJ or LTW
Summary: NoClassDefFoundError is risen after compiling with AspectJ or LTW
Status: NEW
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: unspecified   Edit
Hardware: All All
: P3 critical (vote)
Target Milestone: ---   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-08-24 10:46 EDT by Abraham Nevado CLA
Modified: 2010-09-10 12:27 EDT (History)
2 users (show)

See Also:


Attachments
Test Case (5.63 KB, text/plain)
2010-08-24 10:51 EDT, Abraham Nevado CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Abraham Nevado CLA 2010-08-24 10:46:37 EDT
Build Identifier: 1.6.10

In some circunstances, when you weave a class that uses a type that is not present although in the not-woven class it is not used, when woven you get a ClassNotDefFoundError caused by a Class Not Found Exception trying to access the class that is not present and should not be required.

I will send attach a repro case patch as soon as I get the bug ID....


Reproducible: Always
Comment 1 Abraham Nevado CLA 2010-08-24 10:51:54 EDT
Created attachment 177324 [details]
Test Case

This is the test case to add the test to the 1610 bugs. Not tested if it happens for previous versions.
Comment 2 Abraham Nevado CLA 2010-08-24 11:05:03 EDT
This issue has been identified weaving LifeRay, if you do not exclude com.liferay.util.servlet.SharedSessionServletRequest from the weaver, when it is woven the portal does not work generating a ClassNotDefFoundError for every single request, as JettySharedSessionWrapper -although it is not a Jetty container- tries to be resolved and thus trying to access org.mortbay.jetty.servlet.AbstractSessionManager.SessionIf that is not present as it is running under a non-Jetty application server.

A quick workarround is excluding this class ...
Comment 3 Andrew Clement CLA 2010-09-10 12:27:55 EDT
This is due to the behaviour of the verifier.

In this code:

  public D getConflictMethod (Object o){
    if (Detector.alwaysFalse()){
      return  new C(o);
    } else {
      return new B(o);
    }
  }

There is very little analysis to do, there are no local variables.  In this similar code:

  public D getConflictMethod (Object o){
    D result = null;
    if (Detector.alwaysFalse()){
      result = new C(o);
    } else {
      result = new B(o);
    }
    return result;
  }

The verifier needs to look at the types of C and B to check they fit with the specification for result (type D).

When AspectJ implements after advice it remaps returns that occur in the body of a method to all go through one place, so then it only needs to insert the after advice at one location.  So what basically happens is that in your standard compilation your getConflictMethod has to returns from the body of it.  When woven it has one return at the end and the verifier will need to load C (in the woven case it is stack analysis rather than local variable analysis, but it is much the same thing).

So you can simulate this problem in pure Java, just change your getConflictMethod() to my version above, compile all the java code then remove C.class - when you run Test you will get the same missing class error.

I simplified your testcase by removing the before advice, the after throwing advice and reducing the after advice to just after returning advice. I also changed it to only weave the type containing getConflictMethod.

The 'solution' would be offer a weaver mode where you weave in multiple calls to the after advice ahead of each return, rather than remapping the returns. 

In BcelShadow.weaveAfterReturning you can see it grabbing the advice instructions and then retargetting the branch instructions.  We would need to alter that sequence to leave the returns alone and insert the advice calls in multiple places.

Or if you run -noverify, the code will also work.