1

How can I run the compiled code (.class) java from the java code itself?

I'm doing a kind of providing service like compiling and running java code on server side and giving output to the end user.

Can anyone suggest an approach that will accomplish this?

import java.io.*;

public class demo {

    public static void main(String args[]) throws IOException, InterruptedException {
        int result;
        try {

            System.out.println("command output:");
            Process proc = Runtime.getRuntime().exec("java -cp . demoh");
            InputStream in = proc.getInputStream();
            result = proc.waitFor();

            BufferedInputStream buffer = new BufferedInputStream(proc.getInputStream());

            BufferedReader commandOutput = new BufferedReader(new InputStreamReader(buffer));
            System.out.print(commandOutput);

            String line = null;
            try {
                while ((line = commandOutput.readLine()) != null) {
                    System.out.print(line);
                    System.out.println("command output: " + line);
            }//end while
            commandOutput.close();

            } catch (IOException e) {
                //log and/or handle it  
            }
        } catch (IOException e) {
            System.err.println("IOException raised: " + e.getMessage());
        }
    }
}
4
  • 1
    "i m doing kind of providing service like compiling and running java code on server side and giving out put the end user?" Might as well just install tomcat and give the user access to upload servlets, which would be about the same security nightmare. Actually come to think of it, if you go ahead with that, you might as well give them the keys to your house at the same time. ;) Commented Apr 20, 2012 at 16:12
  • @AndrewThompson can run it in a sandbox Commented Apr 20, 2012 at 16:23
  • 2
    @bizso09 True, but that then means many interesting types of code would not run. Even then, you have to account for programming bugs (OutOfMemroyError, StackOverflowError, endless loops..). In fact, once I had an on-line compiler (no option to run the code). A person who had deep knowledge of the compiler I was using, got in contact and warned me of DOS attacks that were purely based on compiling code. There was (at least long ago) code that could tie up the compiler for 30 minutes or more! Commented Apr 20, 2012 at 16:27
  • @AndrewThompson well you can monitor the compiler and kill it after some time. Once you run the code, you can forward all error messages to the user. Sort of like how platform as a service apps run, i.e Heroku. It's not straightforward, I agree, probably better off using a framework for it. Commented Apr 20, 2012 at 16:36

6 Answers 6

1

If you have the .class files somewhere on disk, simply spawn a new process and run the java command like you would from a command line:

Process p = Runtime.getRuntime().exec("java <java class file>");

After some testing around, the following code worked for me:

public static void main(String args[]) throws IOException, InterruptedException {
    int result;

    try {

        System.out.println("command output:");
        Process proc = Runtime.getRuntime().exec("java -cp . Test");

        InputStream errin = proc.getErrorStream();
        InputStream in = proc.getInputStream(); 
        BufferedReader errorOutput = new BufferedReader(new InputStreamReader(errin));
        BufferedReader output = new BufferedReader(new InputStreamReader(in));
        String line1 = null;
        String line2 = null;
        try {
            while ((line1 = errorOutput.readLine()) != null || 
                   (line2 = output.readLine()) != null) {                   
                if(line1 != null) System.out.print(line1);
                if(line2 != null) System.out.print(line2);               
            }//end while
            errorOutput.close();
            output.close();
        } catch (IOException e) {
            e.printStackTrace(); 
        }//end catc
        result = proc.waitFor();
    } catch (IOException e) {
        System.err.println("IOException raised: " + e.getMessage());
    }
}

Note two things here:

  1. The runtime errors given by the java process are sent to the error stream, not input stream, so you have to read both of them!
  2. You have to read the stream as the process is running. Waiting for the process to finish before reading the streams causes a deadlock because the process output buffer is filled and is waiting for your parent process to read the data, while the parent is waiting for the child to finish!
Sign up to request clarification or add additional context in comments.

10 Comments

thanks tudor but after this i am writing BufferedInputStream buffer = new BufferedInputStream(proc.getInputStream()); BufferedReader commandOutput = new BufferedReader(new InputStreamReader(buffer)); String line=line = commandOutput.readLine(); but there is no contain in line it prints nothing. any idea?
@Madhav Kumar: can you please post this code in the original question?
thanks,.... here is my question.. I am developing webapp like codepad.org and for that i need to compile and run the code that i have got from the client side to server and have do compilation and running of that code server side using java. so i have done kine of compilation at server side and its generating the .class file ,now i want to run that .class file at server side and want to show the out put of that file to the user who has submitted the code. :)
@Madhav Kumar: Please edit your original question and post the code from your first comment so also other people can see it.
:thanks ...please check i have edited original question n posted the code on that i am working. help me.
|
0

Create .jar file and add that file to the build path

1 Comment

thanks for your ans.but i want to build application like codepad.org to provide server side compilation n running it n showing out put to user.so can you guide me how to use .jar file for this?
0

There are still a lot of building/compiling tools, i.e. Ant or Maven, you can check before you write your own.

Comments

0

Try

Process process = Runtime.getRuntime().exec("java " + filePath); // without .class
Scanner output = new Scanner(process.getInputStream());
while (output.hasNext) {
   String token = output.next();
   ...
}

2 Comments

but now doing System.out.print(token.toString()); inside while doesnt prints the output?
@MadhavKumar Does the file have a class and main method?
0

One of the options is to create an instance of the class using the class loader. The class loader can take your class as a byte array and then you can create an instance of it and run it. See this method in the JDK docs.

Comments

0

Here's a sample app that will compile the Java source file, load the class, instantiate an instance, and print out the toString() of the class HelloWorld. I believe you'll need tools.jar on the classpath. The sample code expects the source file in the src folder. The src folder is required on the classpath since the .class file will get generated there by default.

For more control of the Java Compiler, read up on the javax.tools package.

package sourcerunner;

import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;

public class SourceRunner {

    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, InterruptedException {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

        compiler.run(System.in, System.out, System.err, "src/sourcerunner/HelloWorld.java");

        TimeUnit.SECONDS.sleep(1L);

        Class<?> cls = Class.forName("sourcerunner.HelloWorld");

        Object instance = cls.newInstance();

        System.out.println(instance);
    }
}

And here's the HelloWorld class:

package sourcerunner;

public class HelloWorld {

    @Override
    public String toString() {
        return "Hello Java Compiler World.";
    }
}

The above code is insanely insecure. Once you understand the code, modify it to use a new ClassLoader to load and instantiate the class. Make sure the ClassLoader has minimal permissions.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.