This question already has answers here:
Determining location of JVM executable during runtime
(5 answers)
Closed 2 years ago.
I have some Java code that launches a new Java process, effectively using the default system JRE (in my case JDK 8). Instead I need it to run with the version that is running the original process (e.g. JDK 9).
How can I do that? (The solution needs to work on both Java 8 and 9.)
Details
The code currently relies on the default system JRE by simply issuing a java ... command. An alternative would be to use something akin to System.getProperty("java.home") + "/bin/java" (but platform independent), but both have the same problem (for me): They launch a Java process with the JVM version known to the system.
UPDATE: That's utterly wrong, System.getProperty("java.home") indeed does what I want and returns the current JVM's home directory. (Stupid me, I thought I tried that.)
One way to launch with the same Java version, would be to ask the current process for it's executable and reuse that one, but I found no API for that.
Solution for Java 9 only. With
ProcessHandle.current().info().command().map(Paths::get).orElseThrow();
you get a handle to the current java executable: <JAVA_HOME>/bin/java[.exe]
Now, use that (absolute) path with the new Process API to your liking.
If you cannot use the new Java 9 API yet, here you go:
static String getJavaRuntime() throws IOException {
String os = System.getProperty("os.name");
String java = System.getProperty("java.home") + File.separator + "bin" + File.separator +
(os != null && os.toLowerCase(Locale.ENGLISH).startsWith("windows") ? "java.exe" : "java");
if (!new File(java).isFile()) {
throw new IOException("Unable to find suitable java runtime at "+java);
}
return java;
}
For more details you can take a look how we do it in JOSM's restart action, which has the following requirements:
work on Java 8+, Linux, Windows and macOS
work with java running a jar file or class files directly (e.g. from an IDE)
work with Java Web Start and macOS packaged applications
work with paths containing space characters
The code proceeds as follows:
finds the java runtime using java.home system property
checks whether the sun.java.command system property is available (not the case for IBM JVM), then extracts program main class and program arguments from it.
reconstructs the command line either by adding -cp or -jar arguments, depending on what we found at previous step
runs the command using Runtime.getRuntime().exec
There is also a lot of stuff concerning JNLP (WebStart) and macOS applications. I assume you're not interested in it but I can explain it if you want.
Related
From a Java application I want to run another Java application on the same Java installation but in a separate process.
AFAIK for a new process I would use ProcessBuilder to run a command like
java -jar my.jar
but what if java is in a different directory, or should be java.exe since we are on Windows, or java.exe has some other name since the first application was jlinked and jpackaged?
Edit: What I learned meanwhile is that a jpackaged application comes with a native executable that sits in front of the JVM but passes all arguments to the application. That means it is no longer possible to specify an alternative jar to be executed, and some other mechanism is necessary.
If jlink image used within jpackage based apps is built without using the --strip-native-commands flag then the runtime image will contain bin/java (or bin/java.exe and bin/javaw.exe on Windows).
This will mean that you should be able to determine a path to launch a new JVM which works inside or outside of jpackage apps just based on the current runtime's java.home and by appending extra VM arguments in normal way for the classpath and main / module of the other application.
On Windows the environment property echo %PATHEXT% usually contains .EXE so the following should specify the java executable for the current runtime without needing to add the correct file extension on Windows:
String java = Path.of(System.getProperty("java.home"),"bin", "java").toString();
You can test above inside your jpackage and non-jpackaged app with a simple one-liner (note that this is not proper way to use ProcessBuilder):
new ProcessBuilder(java, "-version").start().getErrorStream().transferTo(System.out);
Obviously, the above is no help if you wish to determine whether to use Windows console enabled java.exe versus non-console javaw.exe.
On Windows I run the following command and it work;
java -cp "./libs/*;" SampleJavaApp
When I try to run the same command on Linux (CentOS 6) I get
Error: Could not find or load main class SampleJavaApp
SampleJavaApp has no package
Any insight as to why would be appreciated.
Thanks
UPDATE
The Java Version was the problem, as well as the :
The format of the classpath (-cp argument) uses the operating system path separator, to match the behavior of PATH. So you want : instead of ; for separating paths.
Also, you seem to be using an empty path element when I think you want to explicitly reference the current directory ..
Also, I think the handling of the * wildcard varies by Java implementation, so you need to make sure the versions match.
I wish to open certain java applications (For example, MapTools, part of RPtools) with Oracle Java 6 for compatibility purposes using shell scripts.
In the simplest possible terms, what do I need to do to make a working shell script for an application to launch with a specific java version on Ubuntu?
Note that for maximum usefulness, specific application names should not be used. Instead use tags such as "App" to determine where the name of the application or it's path should go.
Specify absolute path of java executable of the JRE version,
[JRE_HOME]/bin/java -jar jar_name.jar
e.g.
/usr/lib/jvm/oracle-7-jre/bin/java -jar exec.jar
Use the full path to the desired java.exe in your command line.
See Run a JAR file using a specific JRE.
I know this question has been asked/answered several times, but I still couldn't find a solution to this ClassNotFoundException error, because it works on my computer but not on my RasPi (on which I installed OpenJDK7).
My application uses JDBC to access a MySQL database, and that's the main problem. As has been pointed out on lots of websites ([1], [2], [3]), this is, unfortunately, a common problem.
So, I'm using the mysql-connector-java-5.0.8.jar as a driver. My folder structure is something like /src/de/web/project/ I'm calling the main method via java de.web.project.WakeOnLan (which is the main class that starts all other classes etc.) I got the common ClassNotFound exception and therefor added the -cp parameter so I called the project via java -cp .;mysql-connector-java-5.0.8.jar de.web.project.WakeOnLan to add the driver to classpath.
This worked nicely on my Windows computer from command line, but now I want to push this code to my Raspberry Pi and execute it there. As I said, I installed OpenJDK7 there (using apt-get, if this should be important), used SFTP to upload the folder structure and the code to /home/pi/java/ where there is also the ejre1.7.0_10 folder (so the code is now actually in /home/pi/java/de/web/project/).
I now went back to /home/pi/java and entered java -cp .;mysql-connector-java-5.0.8.jar de.web.project.WakeOnLan as I did on my Windows computer, but it refuses to work (I've put the connector in any folder on the way, just in case). When I call this function, I get a long list of hints Java wants to give me which parameters are allowed for java, finally stating: -bash: mysql-connector-java-5.0.8.jar: command not found. I also tried to turn ".;mysql..." around to "mysql...;." which didn't work as well. If I don't include the -cp parameter, my program says "Thread started" and in the next line: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver etc., so the program does indeed start and writes "Thread started" to System.out.
For some reason, it looks like Java on the Pi ignored the second value of the classpath parameter for which I don't see a good reason.
You might just have problem in classpath setting, there is difference for windows and linux
The classpath syntax is OS-dependent. From Wikipedia :
Being closely associated with the file system, the command-line
Classpath syntax depends on the operating system. For example:
on all Unix-like operating systems (such as Linux and Mac OS X), the
directory structure has a Unix syntax, with separate file paths
separated by a colon (":").
on Windows, the directory structure has a Windows syntax, and each
file path must be separated by a semicolon (";").
This does not apply when the Classpath is defined in manifest files,
where each file path must be separated by a space (" "), regardless of
the operating system.
This question already has answers here:
How to call java from C++
(4 answers)
Closed 8 years ago.
I wrote a code in java that adjust the system sound volume based on value supplied as command line argument. I would like to execute this code from my C++ application. What is the best way to do this...
Do I need to install the jdk on the deployment machine?
You can bundle a runtime with your software and then call this from within your program, however, the better solution would be to perform the function that the Java app does natively within your C++ application.
You can run your Java application from C++ as you can run any other executable.
Run "java.exe" with your Java class name as a parameter, as you would do normally when executing Java applications from the command line:
java.exe MyClass myParamToJavaClass
Alternatively you can pack your class in an executable jar archive, in which case your command to run your Java application would look something like this
java.exe -jar MyJarr.jar myParamToJavaClass
Substitute the ".exe" by something else if you aren't running under Windows.
In the examples above i assume that "java.exe" is in a directory defined in your "path" environment variable, as it normally is.
You do not need to install JDK but a JRE needs to be present on the deployment machine.