0

I am making a GUI for a command line program using JavaFX.

If I just pack the program inside the .JAR, can I call it? Or do I need to extract the program into the local machine first before making a process? I ask because since a .JAR is a ZIP file, I suppose you can't just run a file inside the .JAR because it is compressed or something.

Saturn
  • 17,888
  • 49
  • 145
  • 271
  • The command line program that you want to launch, is it a Java program? Or like a native binary? – aioobe May 26 '15 at 05:48
  • @aioobe native binary – Saturn May 26 '15 at 05:48
  • 1
    Then it's the operating system that launches the program. Unless the operating system in question is able to launch programs from within zip-files (which I doubt) you would have to extract the binary and write it to disk before launching. – aioobe May 26 '15 at 05:49
  • 1
    this is a good question and I can imagine future visitors struggling with a similar use case so I took the time to write an exhaustive answer. – aioobe May 26 '15 at 06:22

2 Answers2

1

You have to extract your program first to let the os execute it. There's no way to 'stream' it to ram and execute from there.

chris
  • 1,685
  • 3
  • 18
  • 28
1

You'd have to do this in two steps:

  1. Extract the binary and write it to disk (because the OS is probably only able to launch the program if it's a file on disk)

  2. Launch the program, preferably using ProcessBuilder.

Here's a complete demo:

test.c

#include <stdio.h>

int main() {
    printf("Hello world\n");
    return 0;
}

Test.java

import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Collections;

public class Test {
    public static void main(String[] args) throws Exception {

        Path binary = Paths.get("mybinary");
        Files.copy(Test.class.getResourceAsStream("mybinary"), binary);

        System.out.println("Launching external program...");

        // Needed for Linux at least
        Files.setPosixFilePermissions(binary,
                Collections.singleton(PosixFilePermission.OWNER_EXECUTE));

        Process p = new ProcessBuilder("./mybinary").inheritIO().start();
        p.waitFor();
        System.out.println("External program finished.");
    }
}

Demo

$ cc mybinary.c -o mybinary
$ ./mybinary
Hello world
$ javac Test.java
$ jar -cvf Test.jar Test.class mybinary
$ rm mybinary Test.class
$ ls
mybinary.c  Test.jar  Test.java
$ java -cp Test.jar Test
Launching external program...
Hello world
External program finished.

Further reading:

Community
  • 1
  • 1
aioobe
  • 413,195
  • 112
  • 811
  • 826