Bug 51035 - hasmethod NullPointerException @ isMethodFound(HasMethod.java:180)
Summary: hasmethod NullPointerException @ isMethodFound(HasMethod.java:180)
Status: RESOLVED FIXED
Alias: None
Product: Ant
Classification: Unclassified
Component: Core tasks (show other bugs)
Version: 1.8.2
Hardware: Macintosh Mac OS X 10.5
: P2 normal (vote)
Target Milestone: 1.8.3
Assignee: Ant Notifications List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-04-06 16:00 UTC by Kurt Miller
Modified: 2012-01-19 13:54 UTC (History)
2 users (show)



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Kurt Miller 2011-04-06 16:00:09 UTC
The following condition causes ant to raise a null pointer exception:

    <condition property="boot.java.provides.latest.jdk">
        <and>
            <available
                ignoresystemclasses="true"
                classpath="${boot.java.home}/jre/lib/rt.jar" classname="java.nio.file.Path"/>
            <hasmethod
                ignoresystemclasses="true"
                classpath="${boot.java.home}/jre/lib/rt.jar"
                classname="java.nio.file.Path" method="getFileName"/>
        </and>
    </condition>

BUILD FAILED
/Users/truk/jdk/bsd-port/langtools/make/build.xml:188: java.lang.NullPointerException
        at org.apache.tools.ant.taskdefs.condition.HasMethod.isMethodFound(HasMethod.java:180)
        at org.apache.tools.ant.taskdefs.condition.HasMethod.eval(HasMethod.java:154)
        at org.apache.tools.ant.taskdefs.condition.And.eval(And.java:42)
        at org.apache.tools.ant.taskdefs.ConditionTask.execute(ConditionTask.java:120)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:613)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.apache.tools.ant.TaskAdapter.execute(TaskAdapter.java:154)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
        at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:613)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.Target.execute(Target.java:390)
        at org.apache.tools.ant.helper.ProjectHelper2.parse(ProjectHelper2.java:180)
        at org.apache.tools.ant.ProjectHelper.configureProject(ProjectHelper.java:82)
        at org.apache.tools.ant.Main.runBuild(Main.java:793)
        at org.apache.tools.ant.Main.startAnt(Main.java:217)
        at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
        at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)

removing ignoresystemclasses="true" avoids the NPE but isn't the behavior I need.
Comment 1 Stefan Bodewig 2011-04-07 23:49:36 UTC
This happens when the class cannot be found at all, should be fixed in a few minutes.
Comment 2 Stefan Bodewig 2011-04-08 00:10:29 UTC
OK, usually when the class is not found things are handled differently.

The only way the class can be null is if findClass throws a SecurityException.
I'm not sure whether throwing an exception (like we do when the class
can not be found at all) or returning false would be the better fix.
Comment 3 Kurt Miller 2011-04-08 07:22:58 UTC
(In reply to comment #2)
> OK, usually when the class is not found things are handled differently.
> 
> The only way the class can be null is if findClass throws a SecurityException.
> I'm not sure whether throwing an exception (like we do when the class
> can not be found at all) or returning false would be the better fix.

I agree that we're hitting the SecurityException case. What I don't understand is why that is the case, because the class exists and <available\> test with ignoresystemclasses="true" returns true. Shouldn't hasmethod behave similar to <available\>, such that it can detect if the method exists or not with ignoresystemclasses="true". Is there a way to work-around the SecurityException so it can inspect for the method when ignoresystemclasses="true"?
Comment 4 Stefan Bodewig 2011-04-12 00:00:01 UTC
It looks as if the loadClass method in HasMethod started live as a copy
of Available's.

ignoreSystemClasses was introduced to available with bug 6031 and it also
introduced the special handling for SecurityException.  AFAIU a SecurityException
is raised if you try to load a java.* class from a different classloader than
the bootstrap classloader.

In available's case the use-case is that you may want to check whether a jar
that you are going to use as bootclasspath in a new forked VM or pass to
a compiler.  The behavior "yes, the class is there even if this VM is not
allowed to load it" is reasonable in this case.

In HasMethod's case I lean towards throwing a BuildException that states
we were not allowed to load the class rather than returning false by now.

Ignoring the ignoreSystemClasses setting would in fact test the current
bootstrap classloader rather than the classpath you have specified so I
don't think it would be useful.
Comment 5 Stefan Bodewig 2011-04-20 01:12:21 UTC
svn revision 1095270 creates a better error message.

I don't think there is anything else we could do short of creating a "forked" hasmethod that runs in a separate VM with your provided classpath used as the bootclasspath.