Soo my problem is, that I made some kind of launcher and wrote a method that is being called if you click on the "play" button.
private void PlayButtonActionPerformed(java.awt.event.ActionEvent evt) {
try
{
new ProcessBuilder("src/calc.exe").start();
}
catch (IOException ex)
{
Logger.getLogger(Launcher.class.getName()).log(Level.SEVERE, null, ex);
}
}
The file that is being executed is just a copy of the calculator from Windows and
is in the src folder of my project. (Path is "src/calc.exe")
Everything works fine AS LONG as I don't compile my netbeans project file into a JAR file.
If I run the JAR file and click on the play button - nothing happens.
I really hope you can tell me how to fix this.
(P.S.: calc.exe is not always the name of the program to be run. The filename is determined by an .ini.
calc.exe is only used to test the program.)
First, some context:
A JAR file is an archive, a package (compressed or not) that contains Java bytecode and other resources that can be consumed from inside a JVM.
An EXE file is executable binary file that can only be understandable by Windows/MS-DOS family OSs.
When you run your program without packaging it into a JAR file, all resources (the class file and the executable) are accessible from the OS. Windows will launch the JVM and from inside there you, by means of the ProcessBuilder, instruct the OS to invoke an executable file accessible in a path which is relative to the class performing the execution instruction. Until there, everything is fine and as you said, it works.
However, when you pack your Java class and the executable file in a JAR and invoke the JAR, its contents are no longer accessible for the OS. What is happening is that the OS will launch the JVM and it will process the JAR file to find the executable class (the one in which you invoke the ProcessBuilder). From that class file you now instruct the OS to launch an executable which is in a path relative to the JAR file instead of being relative to the class file performing the invoke instruction. Since the EXE is inside the JAR file instead of being relative to it, execution fails because it can't find the executable.
This is that way because the OS won't look inside the JAR file for a specific file, for the OS the JAR file is just that, a file, not a folder so it will ignore its contents.
So, the conclusion is that, since you are invoking the OS to perform a specific operation in another file, just must place that file outside the JAR and in a relative path to that JAR.
If for some reason you insist on packaging your EXE inside the JAR, then you need to extract it outside the JAR before invoking the ProcessBuilder to a temporary folder and invoke the ProcessBuilder using that new path.
This is sort of a touchy subject.
Whoever commented that JARs are not able to do this is wrong. To the contrary, it is applets that do not have such a permission unless they are signed and validated by the author through Oracle.
You said that it all works fine unless you put it in a JAR. That is probably because of your URI being relative to the Windows filesystem.
The way to usually get the file regardless of the packaging around the reference is to do something like this:
MainClass.class.getResourceAsStream(file);
The static getResourceAsStream will parse the available relative and absolute paths, and if you put your "src/calc.exe" here, it should work.
Another suggestion is to thread the process opening. If you have the program as a single thread, the Java program will hang until the external process is gone and cleaned up.
Related
I don't understand how Java jar files work. I am trying to understand what is possible and not possible when creating a Java jar file. Is it possible to have a String path running normally in a Java jar file? Will this normally work as it works when running main class in eclipse? I mean, I have an absolute path in my main class that grabs the file and reads from it.
public static final String file1 = "C:\\Users\\Documents\\test1.txt";
public static final String file2 = "C:\\Users\\Documents\\test2.txt";
This is what I have when running my program and it works fine. This is inside a class that is called somewhere along when I want to read a file. My question is... will this prevent my jar file from working properly normally AS when running the main class from eclipse?
I have the jar file but what if it doesn't or does it still look for file1 and file2?
It doesn't matter whether that code is in a jar file or not. The strings will still be exactly as they are, and if you pass them to methods that look for files with those paths, it'll look for files with those paths in the file system of the machine where the code is running. It won't look for them inside the jar file.
A Jar file is basically an executable of your project, it is used for example by frontend's who need a backend but don't want to open an IDE for compiling and executing purposes. Your Jar file contains .class files responsible for the execution of your project, you an execute your jar in a server too, so your application will run for more people (if you configure right).
I have a selenium program that is intended to be copied onto other computers before execution. I would like to only have to ship out a runnable jar. On execution the program should extract chromdriver.exe to a new directory in the directory from which the program was executed. The .exe should only be exported if it does not already exist in that exact location. Assuming I do already know the .exe is not there, how do I program the application to extract the .exe File? The resource folder has been added to the class path under sources (I am using eclipse) so the .exe does appear in the jar when I export the project. Now I just need to see how to extract it on execution
Thanks!
I assume that your chromedriver.exe file is contained in your jar file in a package named res. The following code will extract the file to your local harddrive.
InputStream i = this.getClass().getResourceAsStream("/res/chromedriver.exe");
Files.copy(i, new File("c:\\target\\chromedriver.exe").toPath());
You can add a CopyOption if you like.
I want to know how does an executable jar file (which is added as a library) work with the main program.
For example when an executable jar file is added, and if it was not called within the source code of the main program, does it have any effect?
Is an executable jar file the same as a run time library?
An "executable jar file" is simply one that has a class that defines a main method and where the jar file maintains metadata about where to find this main method.
If this jar is not the jar used to launch the JVM, then this metadata is ignored and the jar is treated just like any other jar file (no effect unless explicitly used by something else).
Answer is No, It is just standard JAR file which contains a class with Main method init. This main method's location information gets stored in metadata.
If you run this jar file then this class & thus main method gets called.
Otherwise it is just normal JAR file. You can add it to any application's classpath & it has same effects as other normal JAR files. Main method still exist but won't get executed.
I am developing a small Java application using Swing, that is supposed to run on Windows/Linux and MacOS.
Eventually it will ship as a runnable jar with some config files in the same folder. To load them I need the path to the folder the jar is stored in within the program.
There are already a couple of threads like this one or this one.
My problem is, that all the solutions discussed there work fine, when I run the program from within eclipse or call the runnable jar from a terminal like so:
java -jar /path/to/jar/jarfile.jar
However when I click on the jar file in Cinnamon or Gnome (which is what most of the users will know to do), I do not get the correct paths. (MacOS users report the same issue)
Here is what I've tried so far and what the output is when run via double click (all those display the desired path when run from eclipse or a terminal):
ClassLoader.getSystemClassLoader().getResource(".").getPath()
Output: file:/usr/lib/jvm/java-6-openjdk-common/jre/lib/ext/pulse-java.jar!/
SomeClass.class.getProtectionDomain().getCodeSource().getLocation().getPath();
Output: ./
System.getProperty("user.dir");
Output: /home/myusername
Is there any other way to do it or am I doing something wrong when exporting the jar? Any help would be appreciated!
Cheers
Nick
Make it simple, and use a startup script (.bat/.sh file) to run your application. This startup script will get the path of its own location in the filesystem, and pass it as an argument or system property to the Java application. This has the additional advantage of being able to pass other arguments, like the size of the heap, etc.
On windows, %~dp0 is the path of the directory containing the executed bat file. On Unix, you can use $(dirname $0).
You could store all config files as resources in a jar, and copy them to files in home.dir + ".AppName/".
Painful as it is, the Preferences API, Preferences.systemNodeForPackage, seems the wisest alternative, if there is little structured config data. There is an inputStream method for import; your initial config template could be a resource in the jar.
Just get the class path using System.getProperty("java.class.path") and scan it for your ".jar" name. Note that path separators are OS dependent (File.pathSeparator)
I built a jar file that can run perfectly within netbeans when I click run,
but when I try to run the jar file by double clicking it it does not run, nothing happens..
Double-clicking the jar starts it, but unless you have a GUI application that opens a new window (in a different thread), it most likely finishes and closes before you can see anything.
In these cases you normally run the jar from the console (java -jar ..) to see if there are any exceptions/errors.
Starting an application from the command line would let you debug the problem as Bozho said. But you need to check if you have all the files in dist folder that you need to run your program. For example if you are using a database file to get the data, you need to place this file in the dist folder after program is built. I think the jar file is using a relative path when looking for files.