This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 54358 - Wrong source file is opened in the debugger because getPaths returns HashSet
Summary: Wrong source file is opened in the debugger because getPaths returns HashSet
Status: CLOSED FIXED
Alias: None
Product: debugger
Classification: Unclassified
Component: Code (show other bugs)
Version: 4.x
Hardware: All All
: P2 blocker with 2 votes (vote)
Assignee: Martin Entlicher
URL:
Keywords:
: 54449 72049 73031 76500 (view as bug list)
Depends on:
Blocks: 90398
  Show dependency tree
 
Reported: 2005-02-02 13:08 UTC by gennady
Modified: 2010-04-29 09:20 UTC (History)
5 users (show)

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments
Repro of this issue (2.40 KB, application/octet-stream)
2006-11-14 15:48 UTC, ljandersen
Details

Note You need to log in before you can comment on or make changes to this bug.
Description gennady 2005-02-02 13:08:10 UTC
Suppose we have 2 opened projects: "Working" 
and "Browsing". They both represent the same 
system under development. "Working" contains only 
files currently under development, 
while "Browsing" contains all sources of the 
stable system tree. During debugging, NetBeans 
often opens a source (on breakpoint hit, for 
example), from "Browsing", even the class with 
the breakpoint is in "Working".

I've debugged the issue using NetBeabs sources 
and supposedly found out that the problem is in 
GlobalPathRegistry.getPaths. When a debugger 
session is started (in my case by attaching), the 
debugger calls GlobalPathRegistry.getSourceRoots, 
which in turn calls getPaths(ClassPath.SOURCE). 
getPaths retrieves source paths, which are srores 
as an ArrayList of ClassPath (maintaning order), 
creates a HashSet from it and returns it. 
ClassPath inherits method hash() from Object. 
Therefore, the ordering of source paths in the 
set returning by getPaths depends on the object 
identity, i.e., on their placement in the memory. 
Thus, on different IDE runs the result of the 
source path search will be different, so 
sometimes debugger shows sources correctly and 
sometimes not. 

My suggestion for fixing is to use LinkedHashSet 
instead of HashSet (actually, getSourceRoots use 
LinkedHashSet for storing the source root paths).
Comment 1 Tomas Zezula 2005-02-15 09:03:55 UTC
The GlobalPathRegistry (GPR) does not cause your problem since it is
used only for sources for which the classpath can not be found, it is
a fall back. This should not be your case. ClassPaths are registering
into GPR in undefined order, so returing them in LinkedHashSet will
not help.
The problems is that you have source root(s) owned by 2 or more
projects which is not allowed, see issue:
http://www.netbeans.org/issues/show_bug.cgi?id=54563
There is a bug in the NetBeans 4.0 that it let you to create/open such
projects.
Comment 2 gennady 2005-02-15 09:32:53 UTC
1. I do not have source root(s) owned by 2 or more projects.
2. GPR stores paths in a category (ClassPath.SOURCE, for example) 
using lists. Therefore, if LinkedHashSet is used, the order in GPR 
will be preserved, regardless whether it is defined or not.  
Therefore, you loose nothing using LinkedHashSet. Additionally, as 
I've found, the order is consitent with the order of projects in the 
Projects window and it is good for my configuration.
3. I just did the proposed fix locally and it seems to work.
4. The problem of showing wrong source in debugger exists regardless 
whether my explanation is correct or not. Therefore, I would like 
this issue to be handled further. If this is a result of my project 
configuration, I will appreciate any assistance for correcting this. 
I can provide my project configuration files as attachments or send 
them by e-mail, if necessary.
Comment 3 Tomas Zezula 2005-02-15 10:35:16 UTC
From the bug repport:
"Suppose we have 2 opened projects: "Working" 
and "Browsing". They both represent the same 
system under development. "Working" contains only 
files currently under development."
Is this true (you have sources owned by 2 projects) or not?
GPR stores the ClassPaths in list but the calling of register is not
ordered. It up to project type to call GPR.register.
The problem of showing wrong sources is either caused by 2 projects
opened with same sources, not sure about project configuration. Or
debugger code does not use GPR instead of ClassPath.getClassPath ().
But GPR does not imply in its contract any ordering.
Comment 4 gennady 2005-02-15 11:45:38 UTC
From the bug repport:
"Suppose we have 2 opened projects: "Working" 
and "Browsing". They both represent the same 
system under development. "Working" contains only 
files currently under development."

This is true. But source roots of the projects are different 
directories. "Browsing" owns a directory where the whole developed 
system sits. I have only read-only permissions for it and it is used 
only for browsing. "Working" owns another directory, in my ownership. 
Generally, it is empty. If I need to change something, I check (a) 
file(s) or/and (a) package(s) out into the directory (of "Working"). 
After completing the work, I check the files in. After the system 
in "Browsing" is rebuilt (by someone else), I release unnecessary 
files from "Working". So that, the physical files and directories 
in "Working" are not the same as in "Browsing", but they have the 
same names, structure and similar contents.
As for GPR, as far as I understood by debugging, it is used by 
debugger to establish the source search path when a debugging session 
is started. Maybe GPR does not define the class path ordering, but it 
is certainly the same for each NetBeans run. However, when the path 
is returned as HashSet, its ordering is different for different runs. 
Additionally, path ordering in the debugger is different from the 
ordering in GPR. I see this as a problem.  
Comment 5 Tomas Zezula 2005-02-15 13:23:49 UTC
Thanks, now I understand to your projects layout.
You are right that the ordering will be the same for each NB start and
it will probably depend on the order you opened the projects and on
the order the projects are stored in the OpenProjectList (holds at
least for j2seproject type).
In this case the debugger will probably use the project which was
opened as the first one. But this is still not the solution, the right
solution is to fix the debugger, it should know the project you are
debugging and should use ClassPath.getClassPath () not the GPR,
CP.getClassPath() always leads to right classpath. I will try to look
into debugger.
Comment 6 Tomas Zezula 2005-02-15 13:27:43 UTC
Hanzi, can you explain why the debugger uses the GlobalPathRegistry?
Comment 7 Jan Jancura 2005-04-13 09:28:30 UTC
No chance to fix it in 4.1.
Comment 8 Martin Entlicher 2005-08-16 16:47:32 UTC
It looks like we do not have a notion of the project which is being debugged.
Therefore we use GlobalPathRegistry, which is obviously wrong. We need to know
the project and retrieve the class path from it.
Comment 9 Martin Entlicher 2006-01-31 10:22:49 UTC
*** Issue 72049 has been marked as a duplicate of this issue. ***
Comment 10 gennady 2006-01-31 11:19:14 UTC
In NetBeans 4.1 there is additional place, which causes the same problem: 
SourcePathProviderImpl.java, line 90, in constructor

Set allSourceRoots = new HashSet();
Comment 11 tboerkel 2006-01-31 13:32:04 UTC
Hmm, I understand that it is complicated to determine the right project
automatically, but it would be good enough (for us), if it would use the active
project.
Comment 12 gennady 2006-03-06 14:32:48 UTC
I just want to mention that I fixed this (don't panic, locally at my place by 
downloading sources) in 4.0, 4.1 and 5.0 by replacing HashSet by LinkedHashSet 
in the problematic places. The fix took me a few minutes. But I'm really tired 
to do this with each netbeans release. Can you please do the same and do more 
complex fixup later? There are only two lines of code that should be changed. 
If you want, I can supply the fixed source files.
Comment 13 Tomas Zezula 2006-03-13 09:46:58 UTC
Can you attach the diff to this issue?
I will try to review it and get it through the API reviews into the CVS.
Comment 14 gennady 2006-03-13 13:00:09 UTC
Here you are. The original files are with the "orig" extension.

diff ./debuggerjpda/ant/src/org/netbeans/modules/debugger/projects/SourcePathPro
viderImpl.java.orig ./debuggerjpda/ant/src/org/netbeans/modules/debugger/project
s/SourcePathProviderImpl.java
90c90
<             Set allSourceRoots = new HashSet (
---
>             Set allSourceRoots = new LinkedHashSet (
diff ./java/api/src/org/netbeans/api/java/classpath/GlobalPathRegistry.java.orig
 ./java/api/src/org/netbeans/api/java/classpath/GlobalPathRegistry.java
130c130
<             return Collections.unmodifiableSet(new HashSet(l));
---
>             return Collections.unmodifiableSet(new LinkedHashSet(l));
Comment 15 Martin Entlicher 2006-06-06 15:15:47 UTC
*** Issue 76500 has been marked as a duplicate of this issue. ***
Comment 16 Martin Entlicher 2006-09-05 11:47:07 UTC
*** Issue 54449 has been marked as a duplicate of this issue. ***
Comment 17 Martin Entlicher 2006-09-07 14:55:27 UTC
*** Issue 73031 has been marked as a duplicate of this issue. ***
Comment 18 ljandersen 2006-11-14 15:48:55 UTC
Created attachment 36047 [details]
Repro of this issue
Comment 19 tboerkel 2006-11-28 14:01:57 UTC
When will this be fixed? This is very annoying for us, because we always have to
maintain multiple versions of our application in parallel. Each version has its
own NB project, but almost all sources exist in all versions/projects. So it
happens very often, that NB jumps into the wrong source. Mostly, even closing
the other projects before debugging is no working workaround, you also have to
restart NB. IMHO, this should be a hotfix for NB 5.5. BTW: Eclipse does not have
this problem.
Comment 20 rptmaestro 2007-03-21 20:32:07 UTC
Is it possible to get a fix for this is 5.5.1? This really is a big problem. If
I'm tired of tracing through the debugger and getting the wrong files. Moreover,
it creates a certain level of distrust in the IDE, that I can't rely on it to be
smart enough to know which project sources I'm debugging.
Comment 21 Martin Entlicher 2007-03-22 17:06:36 UTC
Why do you change the version number? If this is a problem since 4.0, it should
stay 4.0.

We plan to fix this into the next trunk milestone - M9. It's too late for 5.5.1
now, we expect the release of 5.5.1 soon and only really critical fixes can go in.

The reason I was reluctant to implement the proposed patch sooner was that I'm
not sure that this is the correct approach to fix this problem.
Projects register source paths into GlobalPathRegistry in no defined order and
projects in Projects view are sorted alphabetically. Thus I do not see a way how
to assure that one project will be consulted for sources sooner than another.

If I understand your setup correctly, you need to search for the file in
"Working" project and if it's not there then pick it up from "Browsing" project. 
How does the compilation and execution assures that it picks Working before
Browsing? Do you have some third project, which depends on both of these in the
correct order? Does Run action work properly? Please provide details about your
setup. Thanks.
Comment 22 tboerkel 2007-03-22 19:12:47 UTC
Why not just use the sources from the active project?
Comment 23 Martin Entlicher 2007-03-23 10:50:32 UTC
Well, I'm afraid that the active project might not be sufficient for
applications composed from many projects. We, unfortunately, do not have a
notion of a group of projects or "meta projects".

But perhaps this could be taken as the default and allow to add source roots
from the rest of the projects in Sources View.
When attaching to NetBeans it would be enough to set "nbbuild" as the main
project then and debugger could easily find the right sources...
We'll consider this, it would be a change in the behavior, so we need to assure
that it will be transparent enough to the users.

We still would like to see the exact use-cases and setup that makes the problem
described in this issue.
Comment 24 tboerkel 2007-03-23 11:34:43 UTC
Our use-case is described in my comment above:

Additional comments from tboerkel Tue Nov 28 14:01:57 +0000 2006
Comment 25 Martin Entlicher 2007-03-23 12:01:21 UTC
Aha, thanks Thomas. So it's slightly different from gennady's usecase.
For you it makes sense to consider just the active (main) project when looking
for sources. The others are independent (and possibly slightly different)
copies, that should be ignored by the debugger.

We'll try to come up with some solution for M9 milestone.
Comment 26 tboerkel 2007-03-27 07:02:32 UTC
Thanks. If the source is not found in the active project, then it should look in
the other projects, just like today.
Comment 27 tboerkel 2007-07-19 09:29:16 UTC
As I understand, NB 6.0 M10 is feature freeze now and this bug is not fixed? 

Shouldn't this bug be fixed in M9?
Comment 28 Marian Mirilovic 2007-07-31 08:42:36 UTC
definitely not for M9 ... Martin please reevaluate
Comment 29 Martin Entlicher 2007-08-08 18:44:22 UTC
I've reimplemented the SourcePathProviderImpl and changed the sources management a bit. That will hopefully solve this
problem.
Currently, when you start debugging a project inside NetBeans IDE (Debug Project), the project's boot class path and
execution class path is remembered in the correct order and used for source opening in Editor. The rest of source roots
that come from other opened projects is appended in alphabetically sorted order (just for convenience, there is no
reliable order defined). Thus all project sources and sources of it's dependent projects should be browsable in correct
order.
When you attach NetBeans debugger to some remote application, then the main project (and it's execution class path) is
taken in the correct order. The rest of source roots that come from other opened projects is appended in alphabetically
sorted order, like in the previous case. I hope that this algorithm solves this issue.
Please verify that it suits your needs and works as you expect.

/shared/data/ccvs/repository/debuggerjpda/projects/src/org/netbeans/modules/debugger/jpda/projects/SourcePathProviderImpl.java,v
 <--  SourcePathProviderImpl.java
new revision: 1.4; previous revision: 1.3
Comment 30 tboerkel 2007-08-13 07:10:47 UTC
Thanks a lot for implementing this and getting it into 6.0!

It works as intented. There is however a small problem.

Example:
I have 3 versions of an application open (3 projects with not exactly identical sources). I have the same source file
from all 3 projects opened in the editor and I have set breakpoints in all 3. Now I attach the debugger and NB tries to
submit all breakpoints from all 3 sources to the running program (some of them will fail, because there is no source
code at that line in the running source). However, when a breakpoint is hit, it stops in the correct source (from the
active project). This results in stopping at lines, where no breakpoint (in the correct source) is set.

This does not happen when starting the program from within NB (not attaching).

If it is an uncorrectable side effect of this fix, then I'd rather live with it instead of losing all that functionality.

Comment 31 Martin Entlicher 2007-08-13 16:10:33 UTC
Thomas, I do not think this is really a side-effect of this fix, this behavior was there before this fix as well IMHO.
The problem is, that during a remote attach, all sources are selected for debugging by default and thus all breakpoints
in these sources are submitted.
But when there are several possible source roots available, it's true that we should probably pick just the one class
for breakpoint submission, which matches the one, that gets selected when debugger stops on that breakpoint. This should
be fixable...
Comment 32 Martin Entlicher 2007-08-14 09:34:23 UTC
It's hopefully fixed now. The breakpoint is submitted only when it comes from the first matched source root:

/shared/data/ccvs/repository/debuggerjpda/src/org/netbeans/modules/debugger/jpda/breakpoints/Bundle.properties,v  <-- 
Bundle.properties
new revision: 1.14; previous revision: 1.13

/shared/data/ccvs/repository/debuggerjpda/src/org/netbeans/modules/debugger/jpda/breakpoints/ClassBasedBreakpoint.java,v
 <--  ClassBasedBreakpoint.java
new revision: 1.24; previous revision: 1.23

/shared/data/ccvs/repository/debuggerjpda/src/org/netbeans/modules/debugger/jpda/breakpoints/LineBreakpointImpl.java,v 
<--  LineBreakpointImpl.java
new revision: 1.40; previous revision: 1.39
Comment 33 tboerkel 2007-08-15 07:51:09 UTC
Thanks again! It works.

But I still get warnings about breakpoints from other source roots. In my opinion, it should ignore those breakpoints
silently.

Attaching to KAPC387:8000
LineBreakpoint P2plusServer.java : 2192 successfully submitted.
Not able to submit breakpoint LineBreakpoint P2plusServer.java : 2197, reason: Breakpoint does not belong into the
preferred source root 'D:\P2plus\Trunk\AppServer\P2Java'.
Invalid LineBreakpoint P2plusServer.java : 2197
Not able to submit breakpoint LineBreakpoint P2plusServer.java : 2182, reason: Breakpoint does not belong into the
preferred source root 'D:\P2plus\Trunk\AppServer\P2Java'.
Invalid LineBreakpoint P2plusServer.java : 2182
Not able to submit breakpoint LineBreakpoint P2plusServer.java : 2177, reason: Breakpoint does not belong into the
preferred source root 'D:\P2plus\Trunk\AppServer\P2Java'.
Invalid LineBreakpoint P2plusServer.java : 2177
Not able to submit breakpoint LineBreakpoint P2plusServer.java : 2180, reason: Breakpoint does not belong into the
preferred source root 'D:\P2plus\Trunk\AppServer\P2Java'.
Invalid LineBreakpoint P2plusServer.java : 2180
User program running
Comment 34 Quality Engineering 2010-04-29 09:20:57 UTC
Verified ... and Closing all issues resolved into NetBeans 6.7 and earlier.