Sorry my newbie question :P If I promp "java -version" in the cmd on a windows system, am I guaranteed that the system will be able to run .jar files if I don't get any error?
From the command line you should be able to invoke "java --version" which will return an error if java is not installed or the currently installed version information.
I guess the only guaranteed way to check for a JRE is to try to run a small Java program.
Or maybe not even that - I suppose conceivably a system could have only part of the Java standard library installed, in which case a small test JAR might work fine but a full program might not. Although I can't imagine why anyone would go to the trouble of setting a system up that way.
Why not run a small class file, which write a value to a file which you then check? If it fails, it doesn't work.
A good value might be the value of the java.version system property.
On Windows, you can check the registry at HKLM\SOFTWARE\JavaSoft\Java Plug-in. From there, each subkey is an installed JRE.
edit Here is C# code that will return an array of strings with the installed JRE's
public string[] GetInstalledJavas() {
// hold the registry subkeys that list the installed JRE's
string[] jres = null;
try {
RegistryKey myKey = Registry.LocalMachine;
myKey = myKey.OpenSubKey(#"SOFTWARE\JavaSoft\Java Plug-in"); // read-only
jres = myKey.GetSubKeyNames();
} catch (Exception myException) {
Console.Writeline(myException.ToString());
}
return jres;
}
Well, obviously not. You can put an empty file called java.bat anywhare in PATH, like C:\Windows\System32. Invoking "java" will not yield any errors but it doesn't mean there's a JRE installed.
I'd actually suggest, if you're only concerned about checking on windows machines, checking the registry for a handler for JNLP... that should guarantee the presence of a relatively recent JRE.
Related
I'm writing a console app that will run in Linux and Windows systems. This app will mainly run on JRE 1.8 environments.
In my code, it needs to get a list of Java processes that run on the host running my application. I have read the posts about jps, which come as a part of JDK, but not JRE, and also it's a separate executable.
My question is, is there any java library that I can use, to list (and ideally also kill some of) the running Java processes? Preferably, I would not want to hassle of calling jps executable with sth like Runtime.exec().
Thanks in advance, for any suggestions.
Oops: I just spotted that you need solutions for JRE1.8, this will only help for JRE9+.
A simple way to scan processes within JRE is to use ProcessHandle.allProcesses(). This will read all processes and you can add filter on simple name match with "java" or "java.exe":
Path java = Path.of("bin", "java.exe"); // use "java" if not on Windows
ProcessHandle.allProcesses()
.filter(ph -> ph.info().command().isPresent())
.filter(ph -> Path.of(ph.info().command().get()).endsWith(java))
.forEach(ph -> {
System.out.println("PID "+ph.pid()+" "+ph.info().command());
})
This approach won't spot Java VMs embedded in EXE - such as from jpackage - so is not as reliable as using JDK jps which does recognise jpackage EXEs and JDK tools like jshell.exe.
I finally found the 3rd party library named Oshi, which apparently does not need JDK and is compatible with Java 1.8: https://github.com/oshi/oshi
For future reference, here is a sample method:
public static List<OSProcess> getOSProcesses() {
SystemInfo si = new SystemInfo();
OperatingSystem os = si.getOperatingSystem();
return os.getProcesses();
}
I need to get the java version from my application that the user has currently installed on their machine. However, the application that I have is installed with a self-contained JRE and when I do a System.getProperty("java.version"), it only returns the version of that self-contained JRE. Is there anyway that I can get the version that is installed on the machine?
The JRE installation are listed in the registry in the key only for Windows, Linux do not have central registry.
HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment
You can make a simple program to test :
public class ShowVersion {
public static void main(String args[]) {
System.out.println(System.getProperty("java.version"));
}
}
Or you can try command prompt
Type java -version
For more you can refer sister site of SO :
https://superuser.com/questions/1221096/how-do-i-check-what-version-of-java-i-have-installed
if you're bundling a JRE (did you check the distribution license for it? Make sure you are allowed to do so) and it's running under that, you get that version back.
If the user were to run it under another JRE, you'd get the version of that JRE. That's just how things work.
In fact if you're using a self-contained JRE the user doesn't even have to have another JRE installed on his system at all, that's the entire point of bundling one in the first place.
Apart from a full file system scan it's impossible to know what other JVMs might be installed, and if you do that you'd have to account for all the different names the Java runtime executables may have depending on the files system you're running on. And after finding all those executables you still have no real way of knowing what version of Java they belong to unless you either do a binary analysis of the executables or somehow detect the information from other files in the directories where those executables are installed, files that may or may not be present depending on the system in question, how it was set up, what JVM is in use, and whether the installation has been manually altered or not.
For example, in the root directory of a JDK installation there is a file called "release" which contains the JVM version, but AFAIK that file isn't required to be there for the JVM to work properly. And your application may not have the rights to the file system to read that file.
You can try looking in known paths e.g. C:\Program Files\Java but unless you scan the entire file system for java or java.exe you will never be sure.
This might not work as expected as in the user that runs your application shouldn't have access to system directories. You can force you application to be started with administrator level access but that would be a security risk.
You requirement seems a bit pointless if you are already bundling a JRE with your application.
You can run cmd command using java (java -version) and use that output to get version.
List<String> cmdArgs = new ArrayList<>();
cmdArgs.add("cmd.exe");
cmdArgs.add("/C");
cmdArgs.add("java -version");
ProcessBuilder processBuilderObj = new ProcessBuilder();
processBuilderObj.command(cmdArgs);
Process process = processBuilderObj.start();
//get inputStream
BufferedReader data = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line1;
while ((line = data.readLine()) != null){
System.out.println(line);
}
While System.getProperty("java.version") returns the version of the Java that your app is running on, calling "java -version" as a system command from your Java app will return the version of the default(installed) Java in your system.
Here are the generic steps to find it programmatically:
Using ProcessBuilder in Java, execute the system command "java -version". This is certainly platform-independent.
Read the output from executed process. The version is usually on the 1st line of the output (smth like java version "1.8.0_191"), so reading the 1st line is enough.
Check using regular expression, if the output matches a string containing a java version, you just parse the version and that will be what you are looking for.
Otherwise, it means the output is an error message (smth like -bash: java: command not found), and there is no Java installed in your system.
control panel
java
Java tab
view
you can see exact version of java used and it's location.
How to check, java is installed on windows system and get fullpath from jvm.dll on client folder?
I used this code, but i dont know how to retrive the current version
TRegistry* reg = new TRegistry(KEY_READ);
reg->RootKey = HKEY_CURRENT_USER;
reg->Access = KEY_ALL_ACCESS;
bool openResult = reg->OpenKey("SOFTWARE\\JavaSoft\\Java Runtime Environment", true);
if(!openResult) // cannot create registry keys, use default values
return;
if(!reg->ValueExists("CurrentVersion")) //it's not exist CuurentVersion
return;
I don't think writing some code or anything like that is needed to see if java is installed.
To see if its installed on windows just go to C:\Program Files\Java if that directory exists then you have java, if its installed on a different directory look in windows programs and it should show if java is installed, if not then you most likely don't have java.
Use this link to see what version you have, but it is recommended to always get the latest version.
Hope this helps, Luke
Edit:
If you want to see if java is installed on another computer programmatically try using a .bat file to see, this link should help.
or use jsmooth to build the jar into an .exe, with this, if java is not installed it will prompt the user to install java.
You can execute a system "Java -version" command from your code. Here is an example for C++. To find the version you just need to parse the result you get, if you get. The String result would provide the information you required.
Meanwhile, to find the path i believe you can do it by iterating through environmental variables and look for JAVA_HOME.
I'm trying to detect if there is a JVM installed and where it is located so I can run java.exe.
All I've managed to find is HKCU\Software\JavaSoft\Java Runtime Environment\<ver>. Is it safe to assume that it is installed in %PROGRAMFILES%\Java\jre<ver>?
I'm trying to do this in C#, but I assume the answer is pretty language agnostic, so any answer is appreciated.
EDIT: Ok silly me, I found How to detect whether java runtime is installed or not on a computer using c# which pointed me at HKLM\Software\JavaSoft\Java Runtime Environment\CurrentVersion which works with HKLM\Software\JavaSoft\Java Runtime Environment\<ver>\JavaHome. I managed to find these instead underneath HKLM\Software\Wow6432Node\JavaSoft\Java Runtime Environment. Is there some way to detect which of these I should be checking without trying to sniff at the CPU type?
I'm going to throw my hat in the ring with the code I've ended up using:
string javaDirectory = null;
// Native registry key - 32b on 32b or 64b on 64b
// Fall back on 32b Java on Win64 if available
RegistryKey javaKey =
Registry.LocalMachine.OpenSubKey("SOFTWARE\\Javasoft\\Java Runtime Environment") ??
Registry.LocalMachine.OpenSubKey("SOFTWARE\\Wow6432Node\\Javasoft\\Java Runtime Environment");
if (javaKey != null)
{
string javaVersion = javaKey.GetValue("CurrentVersion").ToString();
try
{
javaDirectory = javaKey.OpenSubKey(javaVersion).GetValue("JavaHome").ToString();
} catch(NullReferenceException)
{ /* Ignore null deref, means we can't get a directory */ }
}
if (javaDirectory == null)
{
// deal with a lack of Java here.
}
A properly installed JVM on a windows system will (most likely..) respond to the command shell command:
java -version
This does not return the path, but try
java -verbose -version
(At least) one of the lines will contains the substring rt.jar and this line contains the path of the "active" java virtual machine.
Doesn't the JRE install a java.exe in c:\windows?
You can try to get "*JAVA_HOME*" environment variable.
It's could be helpful.
EDIT:
Better idea look por "CLASSPATH" variable.
------- start --------
C:\Documents and Settings\david>set
ALLUSERSPROFILE=...
APPDATA=...
CLASSPATH=.;C:\Archivos de programa\Java\jre6\lib\ext\QTJava.zip
CommonProgramFiles=...
...
----- end ----
From Java, I'm extracting an executable into a location specified using File.createTempFile(). When I try to run my executable, my program hangs when it tries to read the first line of output.
I have discovered that if I try to run the same extracted executable from another program, it works if I specify the directory as C:\Documents and Settings\username\Local Settings\Temp\prog.exe. But if I specify the directory as C:\DOCUME~1\USERNA~1\LOCALS~1\Temp\prog.exe I get the hang.
Is there a way to unmangle the tilde filename in my program so I can specify a directory name that will work?
(And since I always like addressing the language and API design issues, is there any reason why Java File.createTempFile() and java.io.tmpdir have to evaluate to mangled filenames?)
You can use getCanonicalPath() to get the expanded path. E.g.:
try
{
File file = File.createTempFile("abc", null);
System.out.println(file.getPath());
System.out.println(file.getCanonicalPath());
}
catch (IOException e) {}
... produces ...
C:\DOCUME~1\USERNA~1\LOCALS~1\Temp\abc49634.tmp
C:\Documents and Settings\username\Local Settings\Temp\abc49634.tmp
I tested this on XP, but assume it would work similarly on other Windows operating systems.
See #raviaw's answer to your second question.
Wow, I never saw that. The fact is that the environment variable %TEMP% returns a mangled name (this is from my computer):
TEMP=C:\DOCUME~1\raviw\LOCALS~1\Temp
TMP=C:\DOCUME~1\raviw\LOCALS~1\Temp
Assuming that a newly create java VM uses the environment variable to get the temporary folder location, it is not VM's fault that the directories are coming mangled.
And even if you try to use System.getenv() to get the temporary folder, you will still have the same problem.
I would make sure that:
The problem is not caused by the fact that you have a directory called "prog.exe" (based on your question, I am assuming this);
If the file is "prog.exe", if it was not in use by any other program (an antivirus, maybe);
Checking if your computer is sane (this would be a very critical bug for any application that is not a web application and that need temporary files).