Which JDK's distributions can run `javac -sour

2020-02-01 06:05发布

问题:

NOTE: Please do not comment on all the perils of cross-compiling. Thank you.


I have a situation where we need to have Java 6 source compiled for a Java 5 JVM (to be sure that JAX-WS usage is correct). Previously we have done this with ant ant script (which apparently can), but after migrating to Maven we have found that it ends up with javac complaining:

$ javac -source 1.6 -target 1.5
javac: source release 1.6 requires target release 1.6

Is there any Java distribution for Linux (Ubuntu 11.10, x86) where the javac can do this?


EDIT: It appears not, as the limitation is in javac which is the same. The solution (which made this need go away) was to change from the default javac compiler to the eclipse compiler in maven-compiler-plugin.


EDIT: I've found that the Eclipse compiler generates byte code for anonymous inner classes that the javadoc utility disagrees with. I am preparing a bug report for this issue.

回答1:

According to the documentation (Java 5, Java 6), the Oracle SDK should be able to do this when you follow the instructions in the Cross-Compilation Example.

Java 6 should support any version between 1.3 to 1.6 as -target; it doesn't say anything what happens when you use generics and other "compatible" features in the source. The compiler should be able to strip them.

Another culprit in the game might be javac: The compiler might be able to handle this set of arguments but the command line tool might take offense.

In this case, write your own command line using the Java Compiler API. That might allow to pull of some tricks that you can't achieve otherwise.

You can also try the Eclipse compiler (see "Using the batch compiler").

This might fail because of how Java works: Java X code can run on Java Y as long as X <= Y. So while you can easily compile Java 1.4 code for a Java 6 VM, the reverse is not always true.

If everything else fails, write a preprocessor that reads the source and strips unsupported elements (like @Override on interfaces). As long as you compile the code with the annotations once in a while with Java 6, the converted code should be safe as well (unless your code stripper has a bug ...)



回答2:

This answer is an implementation of what @ThorbjørnRavnAndersen explained in the comments as a solution. Using the example code from here, and fixing a few typos, I was able to come up with an example using Eclipse Compiler.

Calculator.java

package example;

// there needs to be a package to avoid A "@WebService.targetNamespace must be specified on classes with no package"
// when running this

import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.xml.ws.Endpoint;

@WebService
public class Calculator {
    @WebMethod
    public int add(int a, int b) {
        return a+b;
    }

    public static void main(String[] args){
        // create and publish an endpoint
        Calculator calculator = new Calculator();
        Endpoint endpoint = Endpoint.publish("http://localhost:8080/calculator", calculator);        
    }
}

pom.xml

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>fi.eis.applications</groupId>
  <artifactId>ws-calculator</artifactId>
  <version>1.0-SNAPSHOT</version>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.3</version>
        <configuration>
          <source>1.6</source>
          <target>1.5</target>
          <compilerId>eclipse</compilerId>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>org.codehaus.plexus</groupId>
            <artifactId>plexus-compiler-eclipse</artifactId>
            <version>2.6</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>
</project>

That you can compile with mvn clean compile and then run with java Calculator on the target/classes/example folder. It will start up a web service on port 8080, which you can test with url http://localhost:8080/calculator?wsdl on your browser.