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 48750 - Permit debugger to find classes based on runtime location
Summary: Permit debugger to find classes based on runtime location
Status: RESOLVED INVALID
Alias: None
Product: debugger
Classification: Unclassified
Component: Java (show other bugs)
Version: 4.x
Hardware: All All
: P3 blocker with 2 votes (vote)
Assignee: issues@debugger
URL:
Keywords:
Depends on:
Blocks: 90398 201754
  Show dependency tree
 
Reported: 2004-09-09 09:45 UTC by Jaroslav Tulach
Modified: 2016-06-20 13:08 UTC (History)
3 users (show)

See Also:
Issue Type: ENHANCEMENT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jaroslav Tulach 2004-09-09 09:45:36 UTC
According to Jesse's comment in issue 48488 the
<nbjpdastart/> task is supposed to survive when no
<classpath/> element is given. It is not so in
case one deletes it from projectized.xml as then
the debug main project results in following
exceptions:

debug:
java.lang.NullPointerException
	at
org.netbeans.modules.debugger.jpda.ant.JPDAStart.execute(JPDAStart.java:165)
	at
org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:275)
	at org.apache.tools.ant.Task.perform(Task.java:364)
	at
org.apache.tools.ant.Target.execute(Target.java:341)
	at
org.apache.tools.ant.Target.performTasks(Target.java:369)
	at
org.apache.tools.ant.Project.executeTarget(Project.java:1214)
	at
org.apache.tools.ant.Project.executeTargets(Project.java:1062)
	at
org.apache.tools.ant.module.bridge.impl.BridgeImpl.run(BridgeImpl.java:216)
	at
org.apache.tools.ant.module.run.TargetExecutor.run(TargetExecutor.java:236)
	at
org.netbeans.core.execution.RunClassThread.run(RunClassThread.java:125)
Caused by: java.lang.NullPointerException
	at
org.netbeans.modules.debugger.jpda.ant.JPDAStart.convertToSourcePath(JPDAStart.java:333)
	at
org.netbeans.modules.debugger.jpda.ant.JPDAStart.createSourcePath(JPDAStart.java:270)
	at
org.netbeans.modules.debugger.jpda.ant.JPDAStart.run(JPDAStart.java:210)
	at org.openide.util.Task.run(Task.java:136)
	at
org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:330)
	at
org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:686)
--- Nested Exception ---
java.lang.NullPointerException
	at
org.netbeans.modules.debugger.jpda.ant.JPDAStart.convertToSourcePath(JPDAStart.java:333)
	at
org.netbeans.modules.debugger.jpda.ant.JPDAStart.createSourcePath(JPDAStart.java:270)
	at
org.netbeans.modules.debugger.jpda.ant.JPDAStart.run(JPDAStart.java:210)
	at org.openide.util.Task.run(Task.java:136)
	at
org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:330)
	at
org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:686)
/usr/local/home/jarda/src/nb_all/nbbuild/templates/projectized.xml:339:
java.lang.NullPointerException
BUILD FAILED (total time: 1 minute 33 seconds)
Comment 1 Jan Jancura 2004-09-09 10:29:11 UTC
I fixed it yesterday, so it should not be reproducible with today builds.
Comment 2 Jaroslav Tulach 2004-09-10 12:22:13 UTC
I can confirm that there are no NPEs, but now my breakpoints do not
work. According to Jesse they should, otherwise there was no point in
telling me to remove the <classpath> definition.
Comment 3 Jan Jancura 2004-09-10 13:45:57 UTC
In this case I need some more info how to reproduce it. At least:
1) whats type of your project ? freeform?
2) do you have sourcepath specified correctly?
3) can you attach you project files?
4) what about content of Sources View, does it contains your sources
after start of debugging or not?
Comment 4 Jaroslav Tulach 2004-09-14 09:06:10 UTC
Remove <classpath> from nbbuild/templates/projectized.xml target debug.

Run NetBeans dev build. Open project autoupdate, make it main project,
put a breakpoint there. Debug. 

The breakpoint is not going to be hit. 
Comment 5 Jesse Glick 2004-09-14 18:35:01 UTC
Not necessarily a debugger bug; could be a problem in e.g.
org.netbeans.JarClassLoader.JarSource.<init>, which provides a
file:/x.jar URL rather than jar:file:/x.jar!/ URL. Not sure what
URLClassLoader does. If URLCL also uses the improper URL, then the
debugger needs to handle it.
Comment 6 Jan Jancura 2004-09-30 14:52:06 UTC
classpath element is voluntary. but in this case you should define
sourcepath element.
nbbuild/templates/projectized.xml does not define it, so you should
not remove classpath one.
Comment 7 Jesse Glick 2004-10-04 17:22:50 UTC
I guess you're missing the point that <sourcepath> is supposed to be
an overriding fallback for where to find sources, but without
<sourcepath>, sources should be found using SFBQ from classes; then
<classpath> can be specified explicitly, or omitted, in which case
class locations are to be found at runtime from the remote VM.
Comment 8 Jan Jancura 2004-10-05 17:23:52 UTC
Whats SFBQ?
Debugger operates on classpath & sourcepath. This is definition valid
at least for 4.0 release, and it can not be changed for this release.
Some other features depends on these definitions.
I do not understand why you can not define classpath.
Comment 9 Jesse Glick 2004-10-05 18:05:51 UTC
SFBQ = SourceForBinaryQuery. If no <sourcepath> is given, sources are
found using SFBQ from the classpath.

Again - for many purposes, passing in an explicit <classpath> is fine.
When the debugger tasks were written, however, they were written to
make it optional to pass in <classpath> (when there is no
<sourcepath>, I mean). If not passed in, the classpath is determined
dynamically by asking the remote VM where code is being loaded from.
This is mainly useful if you have a complex app that loads classpath
elements dynamically, perhaps based on some runtime configuration (as
e.g. NetBeans does), rather than having a simple fixed startup
classpath only - i.e. for "container" or "componentized" apps. In the
case of NB we can work around it by assuming that any
${netbeans.home}/**/*.jar might be loaded by some code, but this trick
 may not work for all apps - you may or may not be able to predict
statically where the app will load from.

It is still desirable to pass an explicit <classpath> if you can,
since it is faster; otherwise there is overhead to find the code
source of loaded classes.

Based on what Yarda says about his experiences, it sounds like this
functionality got broken sometime between the stavbicka merge and now.
Thus being filed as a defect, not an enhancement. I haven't tried it
myself yet. David K. wrote this functionality so he would know better
than I where it was actually implemented.
Comment 10 David Konecny 2004-10-06 11:48:56 UTC
Hanz, you mentioned to me recently that you removed this code
completely during the merge of new debugger, right?
Comment 11 Jan Jancura 2004-10-06 13:38:21 UTC
Debugger uses SourceForBinaryQuery for resolving of sourcepath from
classpath.

Debugger have never used "classpath resolved dynamically by asking the
remote VM where code is being loaded from". This patch has been used
in first prototype of debugger based on new build system, but not in
production code. There are several reasons for it, like performance &
compatibility. This solution is not compatible with Sources View
component too. Thats why we do not plan to use it in future releases.
Comment 12 Jesse Glick 2004-10-06 15:52:37 UTC
In that case (1) the Ant task(s) should be modified to just throw a
BuildException if both <classpath> and <sourcepath> are missing (also
if both are supplied, which makes no sense); (2) this issue should be
WONTFIX I suppose; (3) John Jullion should be notified that any
mention of the Ant debugger tasks in online docs should state that one
or the other of <classpath> or <sourcepath> must be present.
Comment 13 David Konecny 2004-10-06 16:06:11 UTC
Re. "throw a BuildException if both <classpath> and <sourcepath> are
missing (also if both are supplied, which makes no sense)" - if *both
are supplied* does not make much sense, but on the other hand does no
harm. Perhaps might be useful in some obscure cases? I'm not sure, not
very important.
Comment 14 Jesse Glick 2004-10-06 16:20:24 UTC
I can't see any reason to supply both <classpath> and <sourcepath>
since only the <sourcepath> will be used anyway, so IMHO clearer to
forbid it with an exception.
Comment 15 Jesse Glick 2004-10-27 21:06:38 UTC
Summarizing this issue:

Sometimes you are debugging an application which loads classes
dynamically (e.g. using a URLClassLoader) and wish to step into
classes loaded in this way. Currently this can only work if you
include all such code sources directly in the <classpath> given to
<nbjpdastart> (or manually configure a <sourcepath>).

It may be possible for the debugger to notice that a Class in the
remote VM is being loaded from a non-startup ClassLoader, in which
case it is possible to find its origin using
clazz.protectionDomain.codeSource.location.url. This permits e.g.
SourceForBinaryQuery to be used to locate appropriate sources.
Obviously the Sources view would need to show a new entry when this
happens, or something like that.

An early version of the stavbicka debugger did in fact work this way,
if <classpath> was omitted, so it is possible. Robustness and
performance are the primary considerations - sounds like these have
not really been evaluated in detail yet.

The debugger could still require a <classpath> for the startup class
loader, or not; would depend on whether there is an inevitable cost to
using this feature (e.g. occasional problems finding code source).

Workaround from user perspective is to guess which classes are going
to be used in the target VM ahead of time and put those into a
<classpath>. This can be undesirable, especially in a modular build
system where the build script doesn't know details of the component it
is launching; or just in any situation where the actual set of JARs
you will be loading changes acc. to runtime configuration, which is
common enough in "componentized" applications.

Known instances of the workaround in NB sources:

1. nbbuild/build.xml#tryme-debug uses

<classpath>
 <fileset dir="${netbeans.dest.dir}">
  <include name="**/*.jar"/>
 </fileset>
</classpath>

i.e. it just guesses that every class loaded into the VM will be in
some JAR there. Will usually work, unless you load modules from
another location, etc.

This usage is described in the original version of this issue.

2. nbbuild/templates/projectized.xml#debug-test-single-nb uses

<classpath>
 <path refid="test.unit.run.cp"/>
 <pathelement path="${test.unit.debug.cp.extra}"/>
</classpath>

where e.g. ant/nbproject/project.properties specifies

test.unit.debug.cp.extra=\
    ${compile.ant.jar}

since otherwise you cannot step into Ant sources when debugging Ant
module unit tests.

I just found this issue recently - without workaround #2, if you have
sources for ant.jar configured, you can use Run to Cursor to move
around inside Ant classes when debugging an Ant module unit test - but
Step Over does not work (just jumps out to module source code).
Comment 16 David Konecny 2004-11-01 13:39:32 UTC
"Robustness and performance are the primary considerations" - there
were two issues:

#1) one factor which significantly affects performance of debugging is
"class exclusion filter" by which you are saying debugger which
classes it should ignore during stepping through the code. E.g.
debugger steps into java.lang.String class and notifies you about
that. If you have explicit source path it is easy to learn that you do
not have any sources for whole java.* package and so you can set
debugger class exclusion filter to "java.*" and it will never notify
you about these classes anymore. On the other hand without explicit
source path you cannot (safely) do that and can set class exclusion
filter only to "java.lang.String". This way you will end up soon with
very large exclusion list and my experience was that it makes
debugging way slower. Perhaps some heuristic working most of the time
could be used to workaround it.

#2) second issue (not that important) was that any breakpoint used in
the code path of clazz.protectionDomain.codeSource.location.url call
must be disabled otherwise you are in dead cycle. It is doable and
unless user want to debug these methods everything it OK. Once they
need to debug them the behaviour of debugger might not be desirable -
it is doing additional execution which you do not want. But I guess
this is pretty rare.

Otherwise there were really no other issues and everything worked
reliably.
Comment 17 Jiri Prox 2007-09-17 20:17:56 UTC
Obsolete milestone, please reevaluate
Comment 18 Jesse Glick 2016-06-20 13:08:00 UTC
I at least still want this, for the same reasons as before. Why is it “invalid”? “Won’t fix” is understandable if no one else considers it worth the effort to fully support modular applications.