[prev in list] [next in list] [prev in thread] [next in thread] 

List:       bcel-dev
Subject:    DO NOT REPLY [Bug 36110]  New:  -
From:       bugzilla () apache ! org
Date:       2005-08-10 5:17:19
Message-ID: 20050810051719.0520FE0 () ajax ! apache ! org
[Download RAW message or body]

DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG·
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=36110>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND·
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=36110

           Summary: A bug in LocalVariableGen
           Product: BCEL
           Version: unspecified
          Platform: Other
        OS/Version: other
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Main
        AssignedTo: bcel-dev@jakarta.apache.org
        ReportedBy: kk@kohsuke.org


I'm one of the developers working on the Jakarta commons sandbox javaflow project.

This problem is observed in the trunk (as of 2005/08/09), and it's causing some
test failures in the gump build of the said javaflow project.

Here's what I found while tracing through the code.

When LocalVariableGen is created by using the following constructor:


>  public LocalVariableGen(int index, String name, Type type,
>                          InstructionHandle start, InstructionHandle end) {
>    if((index < 0) || (index > Constants.MAX_SHORT))
>      throw new ClassGenException("Invalid index index: " + index);
>    
>    this.name  = name;
>    this.type  = type;
>    this.index  = index;
>    setStart(start);
>    setEnd(end);
>  }


During the setStart method, it registers this newly created LocalVariableGen as
a targeter to the InstructionHandle given by the 'start' parameter.
InstructionHandle.targeters is a HashSet. So adding a LocalVariableGen as a
targter means inserting a LocalVariableGen into a HashSet. This involves in
computing the hashCode.

So from within the setStart method, LocalVariableGen.hashCode() is invoked,
since the end instruction isn't set yet, this returns a hashCode based on just
index and start, ignoring the end field.

Then immediately after the setStart method returns, the above constructor now
sets the end instruction. As a result of this, hash code of the LocalVariableGen
changes. This makes it impossible to update the start of LocalVariableGen
correctly, because LocalVariableGen can no longer remove itself from the
targeter set of the previous 'start' instruction.

In other words, the problem is that the LocalVariableGen class computes its hash
code based on mutable fields, yet at the same time it is used in a HashSet,
where objects are not allowed to change its hash code. To the eyes of a new
comer like me, this seems like a rather fundamental design flaw in the current
BCEL library.



SUGGESTED FIX
=============
implement the hashCode method to return a constant value would fix the problem
at the expense of the performance:

  public int hashCode() { 
    return 42;
  }

Alternatively, instead of using HashSet, use a custom implementation of a Set
where the identity hash code is used instead of Object.hashCode. Although I
haven't tested this approach, I believe this also fixes the problem.

There may be other ways to fix the problem.

-- 
Configure bugmail: http://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.

---------------------------------------------------------------------
To unsubscribe, e-mail: bcel-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: bcel-dev-help@jakarta.apache.org

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic