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.
This happens when the class cannot be found at all, should be fixed in a few minutes.
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.
(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"?
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.
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.