Skip to content

ant: <java fork="false"> cannot run a package-private class (IllegalAccessException); shell java can #599

Description

@LSantha

Summary

ant's <java fork="false"> task cannot run a package-private target class: it fails with IllegalAccessException from org.apache.tools.ant.taskdefs.ExecuteJava. A public class with the same main works fine. (Separately, the task also silently does nothing without an explicit <classpath>.)

Repro (JNode all-plugins boot /full.jgz, serial agent console)

Dir: /devices/hdb1/devtest/ant1 (JFAT).

WriteHello2.java (note: class is not public):

import java.io.*;
class WriteHello2 {
  public static void main(String[] a) throws Exception {
    PrintWriter w = new PrintWriter(new FileWriter("/devices/hdb1/devtest/ant1/done.txt"));
    w.println("ANT RAN OK");
    w.close();
  }
}

build.xml:

<project name="t" default="job">
  <target name="job">
    <java classname="WriteHello2" fork="false" failonerror="true">
      <classpath location="/devices/hdb1/devtest/ant1"/>
    </java>
  </target>
</project>

Run ant from the dir.

Serial output:

Buildfile: build.xml
java.lang.IllegalAccessException: Class org.apache.tools.ant.taskdefs.ExecuteJava can not access a member of class WriteHello2 with modifiers "public static"

done.txt is NOT created.

Same source re-declared as public class WriteHello2 runs fine and creates done.txt.

The same package-private WriteHello2 runs fine with the shell's java WriteHello2 from that directory — the shell JavaCommand uses JCClassLoader + reflection and explicitly accepts non-public classes (mainMethod.setAccessible(true)), so the gap is in ant's reflection path.

Analysis

Ant's ExecuteJava obtains the main method and invokes it; on JNode a non-public class makes the reflective access fail with IllegalAccessException (member modifiers "public static", class not public). The shell java command handles this by calling setAccessible(true); ant appears not to (or JNode's access-check disable path fails for package-private classes).

Suggested fix

Make JNode's reflection / ant ExecuteJava path disable access checks on the target class before invoke, matching the shell's JavaCommand behavior. As a fallback, document that ant <java> target classes must be public.

Workaround

Declare any class run via ant <java> as public, and include an explicit <classpath> element.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions