1

I want to open a Java GUI using another Java program.
It successfully compiled, but it can't be run. It says "cannot load main class". Here is my code:

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;


public class Test {

  public static void main(String[] args) {
    try {
        JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
        jc.run(System.in, System.out, System.err, "src/HelloWorld.java");

        // I think this line has the error
        Runtime.getRuntime().exec("cmd.exe /c start java src/HelloWorld");
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

HelloWorld class:

import javax.swing.JFrame;
public class HelloWorld {
public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setSize(100, 500);
    frame.setVisible(true);
    frame.setResizable(false);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
user3276091
  • 263
  • 3
  • 10
  • 1
    You might want to format your code blocks correctly. That will help the readability of the question. Then, you could also try explaining what/where exactly the error is and providing a some form of debugging output if applicable. – Whymarrh Aug 02 '14 at 00:25
  • This should usually give you a NullPointerException as ToolProvider.getSystemJavaCompiler() normally returns null. How did you solve this? – Dawnkeeper Aug 02 '14 at 00:40
  • Which of the two main() methods do you want to run? Which IDE are you using? – m0skit0 Aug 02 '14 at 00:41
  • @Dawnkeeper I solve this by adding tool.jar in the installed jre – user3276091 Aug 02 '14 at 00:44
  • @m0skit0 I want to run the HelloWorld class from the Test class. I used eclipse. – user3276091 Aug 02 '14 at 00:45
  • Take a look at [this example](http://stackoverflow.com/questions/21544446/how-do-you-dynamically-compile-and-load-external-java-classes/21544850#21544850) to start with... – MadProgrammer Aug 02 '14 at 01:12
  • Alternativly to starting another Java process, you could use another classloader to load the class and run it that way... – MadProgrammer Aug 02 '14 at 01:13
  • I'm guessing there's a classpath problem. – Hot Licks Aug 02 '14 at 02:53

1 Answers1

3

There are any number of possible places your code might fail, for example, it could fail to compile for some reason; java may not be in the OS's search path; the java command may fail, as the src/HelloWorld parameter looks wrong.

I believe your command should look more like java -cp ./src HelloWorld or it should be executed from within the context of the src directory...

You really need to make every effort to diagnose potential issues, such as the DiagnosticCollector for the JavaCompiler and reading the processes InputStream and ErrorStream

Based on your HelloWorld.java and this previous answer I was able generate this example, which can successfully compile and run your class...

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class TestCompile {

    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder(64);

        try {
            DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            try (StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null)) {
                // >>>> Compiler Stage
                // This sets up the class path that the compiler will use.
                // I've added the .jar file that contains the DoStuff interface within in it...
                List<String> optionList = new ArrayList<>();
                optionList.add("-classpath");
                optionList.add(System.getProperty("java.class.path"));

                Iterable<? extends JavaFileObject> compilationUnit
                                = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(new File("src/HelloWorld.java")));
                JavaCompiler.CompilationTask task = compiler.getTask(
                                null,
                                fileManager,
                                diagnostics,
                                optionList,
                                null,
                                compilationUnit);
                if (task.call()) {
                    // <<<< Compiler Stage
                    // >>>> Run stage...
                    ProcessBuilder pb = new ProcessBuilder("java", "-cp", "./src", "HelloWorld");
                    pb.redirectError();
                    Process p = pb.start();

                    InputStreamConsumer.consume(p.getInputStream());

                    p.waitFor();
                    // <<<< Run Stage
                } else {
                    for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
                        System.out.format("Error on line %d in %s%n",
                                        diagnostic.getLineNumber(),
                                        diagnostic.getSource().toUri());
                    }
                }
            } catch (InterruptedException ex) {
                Logger.getLogger(TestCompile.class.getName()).log(Level.SEVERE, null, ex);
            }
        } catch (IOException exp) {
            exp.printStackTrace();
        }
    }

    public static class InputStreamConsumer implements Runnable {

        private InputStream is;

        public InputStreamConsumer(InputStream is) {
            this.is = is;
        }

        public InputStream getInputStream() {
            return is;
        }

        public static void consume(InputStream is) {
            InputStreamConsumer consumer = new InputStreamConsumer(is);
            Thread t = new Thread(consumer);
            t.start();
        }

        @Override
        public void run() {
            InputStream is = getInputStream();
            int in = -1;
            try {
                while ((in = is.read()) != -1) {
                    System.out.print((char)in);
                }
            } catch (IOException exp) {
                exp.printStackTrace();
            }
        }

    }
}

As an aternative to using ProcessBuilder pb = new ProcessBuilder("java", "-cp", "./src", "HelloWorld");, you could actually use...

ProcessBuilder pb = new ProcessBuilder("java", "HelloWorld");
pb.directory(new File("src"));
pb.redirectError();
Process p = pb.start();

Which will launch the java process in within the context of the src directory

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366