0

I have this piece of code that compiles a class called tspClassName, when I compile using this code:

           Process compileProc = null;
        try {
            compileProc = Runtime.getRuntime().exec("javac -classpath ."
                       + File.separator + "src" + File.separator
                       + File.separator + "generated." + tspClassName + ".java -d ." + File.separator + "bin");
        // catch exception
           if (compileProc.exitValue() != 0) 
           {
               System.out.println("Compile exit status: "
                          + compileProc.exitValue());
                      System.err.println("Compile error:" +
                              compileProc.getErrorStream());

it outputs this: "Compile exit status: 2 Compile error:java.io.FileInputStream@17182c1" The class tspClassName.java compiles without errors otherwise, so I am guessing it has to do with the path,and in my eclipse project, the tspClassName.java resides in package homework4.generated inside src, is there something wrong with the path that I use in the code?

thanks

Noona
  • 643
  • 1
  • 14
  • 30

6 Answers6

1

You can use the javax.tools.JavaCompiler or JCI that wrap this functionality.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • Thanks, but I am getting a NULL pointer exception here: JavaCompiler compiler = ToolProvider.getSystemJavaCompiler (); DiagnosticCollector diagnostics = new DiagnosticCollector(); StandardJavaFileManager fileManager = compiler.getStandardFileManager (diagnostics, null, null); because compiler is null, how can I resolve this? – Noona May 18 '10 at 16:22
  • perhaps you don't have a JDK installed? – Bozho May 18 '10 at 16:27
  • No I have it it installed here: C:\Sun\SDK\jdk – Noona May 18 '10 at 16:40
1

Your Java code runs a command that looks something like this:

javac -classpath ./src//generated.ClassName.java -d ./bin

I don't think that's what you want. I think you need to change your Java code so it maybe generates something like:

javac -classpath . src/generated/ClassName.java -d ./bin
                  ^

Note the space after the classpath (".").

Michael
  • 34,873
  • 17
  • 75
  • 109
  • thanks, I did that, but using debug now I found out that the program stops here: compileProc.waitFor(); what can cause this? – Noona May 18 '10 at 16:42
  • @Noona: more than likely there's compilation error (try to manually compile the `.java` file to confirm this). You need to drain the `Process`'s stdin and stderr, or else they block. – polygenelubricants May 18 '10 at 16:47
  • the .java file is in my eclipse project, and it's compiled without errors there. – Noona May 18 '10 at 16:51
  • the command should be like this (i forgot homework4 earlier, but still, there had to be src twice): "javac -classpath ./src src/homework4/generated/ClassName.java -d ./bin" .replace("/", File.separator) .replace("ClassName", tspClassName); – Noona May 18 '10 at 18:09
  • Try draining the input and output streams like polygenelubricants suggested in his answer. – Michael May 19 '10 at 15:47
0

The problem could be with the file location instead of using single value parameter for exec() try 3 parameter method which has the command, environment and location as parameters which helps us to move to the specified location and execute the command

check 6 and 8 methods for reference http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html

 Process compile = Runtime.getRuntime().exec("javac "+fname,null,new File(dir));
0

firstly you should use apache exec library if you want to use processes like that. Apache exec library makes things very easy.

Secondly you should print your std output and std error streams of your process which you are executing. Without them its no way to know whats being executed and what's it doing.

Thirdly, try to print the full cmd line which the process is executing. Copy that cmd line and try to run it manually. Most of the time you would find your issues this way.

And finally if your aim is just to compile a class / generate or modify a class file at runtime give this a good read and try. It has examples too. You could also try code generation / class manipulation libraries like BCEL, JavaAssist etc.

Best of luck.

Nazgul
  • 1,892
  • 1
  • 11
  • 15
0

I think the proper way to do this kind of work is programatically using the javax.tools API, not an external process:

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler()

Reference:

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
0

I recommend doing something like this:

    String command = String.format(
        "javac -classpath . src%1$sgenerated%1$s%2$s.java -d .%1$sbin",
        File.separator,
        tspClassName
    );
    LOG("Executing " + command);
    //... exec(command) etc

... where LOG is whatever your logging framework uses to log the command to be executed. This will help debugging immensely, since it was pointed out that the command you built is ill-constructed.

Alternately you can also build the string using replace

    String command =
        "javac -classpath . src/generated/ClassName.java -d ./bin"
        .replace("/", File.separator)
        .replace("ClassName", tspClassName);

This is perhaps more readable.


On draining Process streams

OP's comment suggests that waitFor() never returns. This is likely caused by compilation errors/warnings in javac process.

From the API:

Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.

You need to continuously drain the Process.getOutputStream() et.al.

See also

  • Java Puzzlers, Puzzle 82: Beer Blast

Related questions

Community
  • 1
  • 1
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623