Bug 70201 - Branch target offset too large for short
Summary: Branch target offset too large for short
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.2   Edit
Hardware: PC Windows 2000
: P3 critical (vote)
Target Milestone: 1.2.1   Edit
Assignee: Adrian Colyer CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 38168 (view as bug list)
Depends on:
Blocks:
 
Reported: 2004-07-16 04:55 EDT by Torsten Lull CLA
Modified: 2004-10-21 04:32 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
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