Bug 70201

Summary: Branch target offset too large for short
Product: [Tools] AspectJ Reporter: Torsten Lull <Torsten.Lull>
Component: CompilerAssignee: Adrian Colyer <adrian.colyer>
Status: RESOLVED FIXED QA Contact:
Severity: critical    
Priority: P3 CC: jim-aj
Version: 1.2   
Target Milestone: 1.2.1   
Hardware: PC   
OS: Windows 2000   
Whiteboard:

Description Torsten Lull CLA 2004-07-16 04:55:25 EDT
I run the compiler with the following command line:
/cygdrive/d/Tools/Java/aspectj12/bin/ajc.sh -Xreweavable -inpath . -d . Time.aj

I get the following error output:

ABORT

Exception thrown from AspectJ 1.2

This might be logged as a bug already -- find current bugs at
  http://bugs.eclipse.org/bugs/buglist.cgi?product=AspectJ&component=Compiler

Bugs for exceptions thrown have titles File:line from the top stack,
e.g., "SomeFile.java:243"

If you don't find the exception below in a bug, please add a new bug
at http://bugs.eclipse.org/bugs/enter_bug.cgi?product=AspectJ
To make the bug a priority, please include a test program
that can reproduce this exception.
Branch target offset too large for short
Branch target offset too large for short
org.apache.bcel.generic.ClassGenException: Branch target offset too large for sh
ort
        at org.apache.bcel.generic.BranchInstruction.dump(BranchInstruction.java
:99)
        at org.apache.bcel.generic.InstructionList.getByteCode(InstructionList.j
ava:980)
        at org.apache.bcel.generic.MethodGen.getMethod(MethodGen.java:616)
        at org.aspectj.weaver.bcel.LazyMethodGen.getMethod(LazyMethodGen.java:32
4)
        at org.aspectj.weaver.bcel.LazyClassGen.writeBack(LazyClassGen.java:395)

        at org.aspectj.weaver.bcel.LazyClassGen.getJavaClass(LazyClassGen.java:4
24)
        at org.aspectj.weaver.bcel.BcelWeaver.getClassFilesFor(BcelWeaver.java:6
41)
        at org.aspectj.weaver.bcel.BcelWeaver.weaveAndNotify(BcelWeaver.java:619
)
        at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:563)
        at org.aspectj.ajdt.internal.compiler.AjCompilerAdapter.weave(AjCompiler
Adapter.java:239)
        at org.aspectj.ajdt.internal.compiler.AjCompilerAdapter.afterCompiling(A
jCompilerAdapter.java:114)
        at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:376)

        at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performCompilat
ion(AjBuildManager.java:601)
        at org.aspectj.ajdt.internal.core.builder.AjBuildManager.doBuild(AjBuild
Manager.java:160)
        at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBu
ildManager.java:94)
        at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:102)
        at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:53)
        at org.aspectj.tools.ajc.Main.run(Main.java:280)
        at org.aspectj.tools.ajc.Main.runMain(Main.java:217)
        at org.aspectj.tools.ajc.Main.main(Main.java:79)


1 fail|abort
Signal 127

I generate the file Time.aj automatically. The target() statements should
restrict the weaving to some classes. Time.aj looks like this:

import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import org.aspectj.lang.JoinPoint;

aspect Time {
  Map tm = new HashMap();
   class ProfileContainer {
     long calls = 0;
     long call_stack = 0;
     long time;
     long curr_time;

     public void print() {
       System.out.println("   Calls: "+calls);
       System.out.println("   Acc time: "+(double)(time/1000));
       System.out.println("   Avg time: "+(((double)(time/calls))/1000));
     }
     public String toString() {
       return ("calls="+calls+" time="+time);
     }
   }


  before():
    // fill targets
(
target(de.rochade.srap.SrapExceptionInformation) ||
target(de.rochade.srap.SrapObjectNotFoundException) ||
target(de.rochade.srap.SrapScriptRuntimeException) ||
target(de.rochade.srap.SrapInternalException) ||
target(de.rochade.srap.SrapResultSetException) ||
target(de.rochade.srap.SrapException) ||
target(de.rochade.srap.executable.ServerControl) ||
target(de.rochade.srap.executable.Server) ||
target(de.rochade.srap.convenient.RochadeSupport) ||
target(de.rochade.srap.convenient.RunScriptSupport) ||
target(de.rochade.srap.convenient.ResultSetSupport) ||
target(de.rochade.srap.convenient.ApplicationSupport) ||
target(de.rochade.srap.convenient.DatabaseSupport) ||
target(de.rochade.srap.convenient.ConnectionSupport) ||
target(de.rochade.srap.SrapScriptCode) ||
target(de.rochade.srap.SrapScriptLoader) ||
target(de.rochade.srap.SrapAdaptor) ||
target(de.rochade.srap.RoSOAPService) ||
target(de.rochade.srap.CommonSetData) ||
target(de.rochade.srap.RoSOAPId) ||
target(de.rochade.srap.ResultSetFactory) ||
target(de.rochade.srap.RunScript) ||
target(de.rochade.srap.Application) ||
target(de.rochade.srap.Database) ||
target(de.rochade.srap.Connection) ||
target(de.rochade.srap.Rochade) ||
target(de.rochade.srap.ResultSet) ||
target(de.rochade.srap.Startup) ||
target(de.rochade.script.ScriptCodeAdapter) ||
target(de.rochade.script.RPLScriptCode) ||
target(de.rochade.script.RoExecutableScriptLoader) ||
target(de.rochade.script.RoExecutableScriptCode) ||
target(de.rochade.script.JSScriptCode) ||
target(de.rochade.rpl.StdOutTraceCallback) ||
target(de.rochade.rpl.StdInOutInformCallback) ||
target(de.rochade.rpl.RPLTrace) ||
target(de.rochade.rpl.RPLTokenizer) ||
target(de.rochade.rpl.RPLInterpreter) ||
target(de.rochade.rpl.RPLInvokeException) ||
target(de.rochade.rpl.RPLExtObj) ||
target(de.rochade.rpl.RPLException) ||
target(de.rochade.ap.HierarchyApplicationName) ||
target(de.rochade.ap.ApUserExit) ||
target(de.rochade.ap.ApUser) ||
target(de.rochade.ap.ApQueryVersions) ||
target(de.rochade.ap.ApplicationName) ||
target(de.rochade.ap.Application) ||
target(de.rochade.ap.ApNsAttrContentsContainer) ||
target(de.rochade.ap.ApMetaModelType) ||
target(de.rochade.ap.ApMetaModelAttribute) ||
target(de.rochade.ap.ApLinkIdentifier) ||
target(de.rochade.ap.ApIdentifier) ||
target(de.rochade.ap.ApDatabase) ||
target(de.rochade.ap.ApAttrContentsContainerFac) ||
target(de.rochade.ds.ValueRange) ||
target(de.rochade.ds.ValueAttrContentsContainer) ||
target(de.rochade.ds.UserExitException) ||
target(de.rochade.ds.UserExit) ||
target(de.rochade.ds.User) ||
target(de.rochade.ds.TVBAttrContentsContainer) ||
target(de.rochade.ds.TextAttrContentsContainer) ||
target(de.rochade.ds.StringAttrContentsContainer) ||
target(de.rochade.ds.Server) ||
target(de.rochade.ds.SdcacInputException) ||
target(de.rochade.ds.ScriptLoader) ||
target(de.rochade.ds.ScriptCode) ||
target(de.rochade.ds.RoContext) ||
target(de.rochade.ds.Rochade) ||
target(de.rochade.ds.QueryVersions) ||
target(de.rochade.ds.QuerySli) ||
target(de.rochade.ds.QuerySdcac) ||
target(de.rochade.ds.QuerySdc) ||
target(de.rochade.ds.QueryPath) ||
target(de.rochade.ds.QueryFactory) ||
target(de.rochade.ds.QueryCmpVersions) ||
target(de.rochade.ds.QueryComparison) ||
target(de.rochade.ds.Query) ||
target(de.rochade.ds.NotFoundException) ||
target(de.rochade.ds.MetaModelType) ||
target(de.rochade.ds.MetaModelLinkAttribute) ||
target(de.rochade.ds.MetaModelException) ||
target(de.rochade.ds.MetaModelAttribute) ||
target(de.rochade.ds.MetaModel) ||
target(de.rochade.ds.LinkIdentifier) ||
target(de.rochade.ds.LinkAttrContentsContainer) ||
target(de.rochade.ds.InvalidTypeException) ||
target(de.rochade.ds.InvalidOperationException) ||
target(de.rochade.ds.InvalidLinkException) ||
target(de.rochade.ds.InvalidAttributeException) ||
target(de.rochade.ds.IdentifierName) ||
target(de.rochade.ds.IdentifierCollection) ||
target(de.rochade.ds.Identifier) ||
target(de.rochade.ds.ICTraverseAction) ||
target(de.rochade.ds.ICNodeCmp) ||
target(de.rochade.ds.ICNodeAction) ||
target(de.rochade.ds.ICNode) ||
target(de.rochade.ds.ICIterator) ||
target(de.rochade.ds.ICCollAction) ||
target(de.rochade.ds.HypTxtAttrContentsContainer) ||
target(de.rochade.ds.DsConst) ||
target(de.rochade.ds.DateAttrContentsContainer) ||
target(de.rochade.ds.DataStoreName) ||
target(de.rochade.ds.DataStore) ||
target(de.rochade.ds.Database) ||
target(de.rochade.ds.ConstIdentifier) ||
target(de.rochade.ds.CloneException) ||
target(de.rochade.ds.BlobAttrContentsContainer) ||
target(de.rochade.ds.BaseAttrContentsContainer) ||
target(de.rochade.ds.Attribute) ||
target(de.rochade.ds.AttrContentsContainerHelper) ||
target(de.rochade.ds.AttrContentsContainerFac) ||
target(de.rochade.ds.AttrContentsContainer) ||
target(de.rochade.ds.AlreadyExistsException) ||
target(de.rochade.ds.AccessControlException) ||
target(de.rochade.util.StringUtilities) ||
target(de.rochade.util.RoObservable) ||
target(de.rochade.util.RoObserver) ||
target(de.rochade.util.RoException) ||
target(de.rochade.util.RPLTokenizer) ||
target(de.rochade.util.Logger)) &&
    call(public * de.rochade..*(..)) {
    synchronized (tm) {
      ProfileContainer pc = (ProfileContainer)tm.get(getKey(thisJoinPoint));
      if (pc == null) {
        pc = new ProfileContainer();
        tm.put(getKey(thisJoinPoint), pc);
      }
      pc.calls++;
      pc.call_stack++;
      pc.curr_time = System.currentTimeMillis();
    }
    //System.out.println("before "+getKey(thisJoinPoint));
  }

  after() returning:
    // fill targets
(
target(de.rochade.srap.SrapExceptionInformation) ||
target(de.rochade.srap.SrapObjectNotFoundException) ||
target(de.rochade.srap.SrapScriptRuntimeException) ||
target(de.rochade.srap.SrapInternalException) ||
target(de.rochade.srap.SrapResultSetException) ||
target(de.rochade.srap.SrapException) ||
target(de.rochade.srap.executable.ServerControl) ||
target(de.rochade.srap.executable.Server) ||
target(de.rochade.srap.convenient.RochadeSupport) ||
target(de.rochade.srap.convenient.RunScriptSupport) ||
target(de.rochade.srap.convenient.ResultSetSupport) ||
target(de.rochade.srap.convenient.ApplicationSupport) ||
target(de.rochade.srap.convenient.DatabaseSupport) ||
target(de.rochade.srap.convenient.ConnectionSupport) ||
target(de.rochade.srap.SrapScriptCode) ||
target(de.rochade.srap.SrapScriptLoader) ||
target(de.rochade.srap.SrapAdaptor) ||
target(de.rochade.srap.RoSOAPService) ||
target(de.rochade.srap.CommonSetData) ||
target(de.rochade.srap.RoSOAPId) ||
target(de.rochade.srap.ResultSetFactory) ||
target(de.rochade.srap.RunScript) ||
target(de.rochade.srap.Application) ||
target(de.rochade.srap.Database) ||
target(de.rochade.srap.Connection) ||
target(de.rochade.srap.Rochade) ||
target(de.rochade.srap.ResultSet) ||
target(de.rochade.srap.Startup) ||
target(de.rochade.script.ScriptCodeAdapter) ||
target(de.rochade.script.RPLScriptCode) ||
target(de.rochade.script.RoExecutableScriptLoader) ||
target(de.rochade.script.RoExecutableScriptCode) ||
target(de.rochade.script.JSScriptCode) ||
target(de.rochade.rpl.StdOutTraceCallback) ||
target(de.rochade.rpl.StdInOutInformCallback) ||
target(de.rochade.rpl.RPLTrace) ||
target(de.rochade.rpl.RPLTokenizer) ||
target(de.rochade.rpl.RPLInterpreter) ||
target(de.rochade.rpl.RPLInvokeException) ||
target(de.rochade.rpl.RPLExtObj) ||
target(de.rochade.rpl.RPLException) ||
target(de.rochade.ap.HierarchyApplicationName) ||
target(de.rochade.ap.ApUserExit) ||
target(de.rochade.ap.ApUser) ||
target(de.rochade.ap.ApQueryVersions) ||
target(de.rochade.ap.ApplicationName) ||
target(de.rochade.ap.Application) ||
target(de.rochade.ap.ApNsAttrContentsContainer) ||
target(de.rochade.ap.ApMetaModelType) ||
target(de.rochade.ap.ApMetaModelAttribute) ||
target(de.rochade.ap.ApLinkIdentifier) ||
target(de.rochade.ap.ApIdentifier) ||
target(de.rochade.ap.ApDatabase) ||
target(de.rochade.ap.ApAttrContentsContainerFac) ||
target(de.rochade.ds.ValueRange) ||
target(de.rochade.ds.ValueAttrContentsContainer) ||
target(de.rochade.ds.UserExitException) ||
target(de.rochade.ds.UserExit) ||
target(de.rochade.ds.User) ||
target(de.rochade.ds.TVBAttrContentsContainer) ||
target(de.rochade.ds.TextAttrContentsContainer) ||
target(de.rochade.ds.StringAttrContentsContainer) ||
target(de.rochade.ds.Server) ||
target(de.rochade.ds.SdcacInputException) ||
target(de.rochade.ds.ScriptLoader) ||
target(de.rochade.ds.ScriptCode) ||
target(de.rochade.ds.RoContext) ||
target(de.rochade.ds.Rochade) ||
target(de.rochade.ds.QueryVersions) ||
target(de.rochade.ds.QuerySli) ||
target(de.rochade.ds.QuerySdcac) ||
target(de.rochade.ds.QuerySdc) ||
target(de.rochade.ds.QueryPath) ||
target(de.rochade.ds.QueryFactory) ||
target(de.rochade.ds.QueryCmpVersions) ||
target(de.rochade.ds.QueryComparison) ||
target(de.rochade.ds.Query) ||
target(de.rochade.ds.NotFoundException) ||
target(de.rochade.ds.MetaModelType) ||
target(de.rochade.ds.MetaModelLinkAttribute) ||
target(de.rochade.ds.MetaModelException) ||
target(de.rochade.ds.MetaModelAttribute) ||
target(de.rochade.ds.MetaModel) ||
target(de.rochade.ds.LinkIdentifier) ||
target(de.rochade.ds.LinkAttrContentsContainer) ||
target(de.rochade.ds.InvalidTypeException) ||
target(de.rochade.ds.InvalidOperationException) ||
target(de.rochade.ds.InvalidLinkException) ||
target(de.rochade.ds.InvalidAttributeException) ||
target(de.rochade.ds.IdentifierName) ||
target(de.rochade.ds.IdentifierCollection) ||
target(de.rochade.ds.Identifier) ||
target(de.rochade.ds.ICTraverseAction) ||
target(de.rochade.ds.ICNodeCmp) ||
target(de.rochade.ds.ICNodeAction) ||
target(de.rochade.ds.ICNode) ||
target(de.rochade.ds.ICIterator) ||
target(de.rochade.ds.ICCollAction) ||
target(de.rochade.ds.HypTxtAttrContentsContainer) ||
target(de.rochade.ds.DsConst) ||
target(de.rochade.ds.DateAttrContentsContainer) ||
target(de.rochade.ds.DataStoreName) ||
target(de.rochade.ds.DataStore) ||
target(de.rochade.ds.Database) ||
target(de.rochade.ds.ConstIdentifier) ||
target(de.rochade.ds.CloneException) ||
target(de.rochade.ds.BlobAttrContentsContainer) ||
target(de.rochade.ds.BaseAttrContentsContainer) ||
target(de.rochade.ds.Attribute) ||
target(de.rochade.ds.AttrContentsContainerHelper) ||
target(de.rochade.ds.AttrContentsContainerFac) ||
target(de.rochade.ds.AttrContentsContainer) ||
target(de.rochade.ds.AlreadyExistsException) ||
target(de.rochade.ds.AccessControlException) ||
target(de.rochade.util.StringUtilities) ||
target(de.rochade.util.RoObservable) ||
target(de.rochade.util.RoObserver) ||
target(de.rochade.util.RoException) ||
target(de.rochade.util.RPLTokenizer) ||
target(de.rochade.util.Logger)) &&
    call(public * de.rochade..*(..)) {
    //System.out.println("after "+getKey(thisJoinPoint));
    synchronized (tm) {
      ProfileContainer pc = (ProfileContainer)tm.get(getKey(thisJoinPoint));
      pc.call_stack--;
      if (pc.call_stack == 0)
        pc.time += System.currentTimeMillis() - pc.curr_time;
    }
  }

  after(): execution(* de.rochade..main(String[])) {
    System.out.println("after main");
    Map.Entry me;
    Set s = tm.entrySet();
    Iterator iter = s.iterator();
    for (int i = s.size(); i > 0; i--) {
      me = (Map.Entry)iter.next();
      System.out.println("Method: " + me.getKey());
      ((ProfileContainer)me.getValue()).print();
    }
  }

  protected static StringBuffer sb = new StringBuffer();
  protected static final String getKey(JoinPoint jp) {
    Object t = jp.getTarget();
    if (t == null) {
       return (jp.toLongString());
    }

    sb.setLength(0);
    sb.append(jp.toLongString());
    // lastIndexOf == JDK1.4
    int idx2 = sb.lastIndexOf(".");
    int idx1 = sb.lastIndexOf(" ", idx2);
    idx1++;
    sb.replace(idx1, idx2, t.getClass().getName());
    return (sb.substring(0));
  }
}

Nearly the same happens if I hold all project files in a *.lst file, but this
set of files is larger than the classes mentioned in the target statements.

Is there any restriction in the number of files AspectJ can deal with?
Comment 1 Andrew Clement CLA 2004-08-06 05:43:23 EDT
*** Bug 38168 has been marked as a duplicate of this bug. ***
Comment 2 Adrian Colyer CLA 2004-08-09 11:54:33 EDT
There is no restriction on the number of files that AspectJ can handle, but 
there is a Java restriction of the maximum length of a method (see section 4.10 
of the JLS). With so many 'target' statements, AspectJ has to generate a method 
containing a very large 'if' test. This exceeds the maximum method length 
supported by the JVM. 

The fix will be to detect this situation and put out an error message akin to 
the one created if a 'regular' method exceeds this limit, rather than have the 
compiler crash with a Bcel exception.
Comment 3 Adrian Colyer CLA 2004-08-09 12:48:42 EDT
With the fix in place the compiler output will now be (from my test case):

/home/colyer/workspaces/aspectjdev/tests/bugs/VeryLongBranch.java [error] 
problem generating method B.foo : Branch target offset too large for short
(no source information available)

1 error

Not the most informative message in the world, but accurate at least (and doing
any better would require parsing of the string message text produced by BCEL
exceptions and I really don't want to go there.)
Comment 4 Adrian Colyer CLA 2004-08-10 12:04:14 EDT
Fix now available in latest development jar from AspectJ download page.
Comment 5 Adrian Colyer CLA 2004-10-21 04:32:58 EDT
Fix released as part of AspectJ 1.2.1