Issue
I'm trying to run windows CLI command from java. I got an issue when parsing results but only when running the code as a runnable jar from cli, from within eclipse it runs fine
private static List<String> runWindowsCommandAsRuntime(String command) {
List<String> out = new ArrayList<String>();
String[] comm = {
"C:\\Windows\\System32\\cmd.exe",
"/S",
"/K",
"\""+command+"\"",
"&",
"exit" //devo uscire o il processo CMD resta appeso e non esce l'output
};
String dbg = "";
for(String s : comm)
dbg += s + " ";
System.out.println("COMMAND: "+dbg);
try {
Runtime rt = Runtime.getRuntime();
Process p = rt.exec(comm);
//get the output
out.addAll(
new BufferedReader(new InputStreamReader(p.getInputStream()))
.lines().toList() //the exception is thrown here
);
int exitVal = p.exitValue();
System.out.println("Exited with error code " + exitVal);
p.destroy();
} catch (Exception ex) {
Utility.logException("Utility(SystemWindows)", ex);
return null;
}
return out;
}
// sample call: runWindowsCommandAsRuntime("WMIC OS Get Caption,Version");
When I run the program trough eclipse it works fine,
when I call it from cli (java -jar my_program.jar
) it starts then throws this
I checked the java version and is both on eclipse and from cli java 11
Exception in thread "main" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:61)
Caused by: java.lang.NoSuchMethodError: java.util.stream.Stream.toList()Ljava/util/List;
Solution
Explanation: You are trying to call .toList() on a stream, and streams don't have the .toList() method (in Java < 16), therefore you have to use a Collector.
Short answer:
you could either use .collect(Collectors.toList())
instead of .toList()
if you want to run your program with Java < 16, or you could use .toList()
on the stream (as you are doing now) but run it with at least Java 16.
And your entire code should look something like this, if you would like to run it with Java older than 16:
private static List<String> runWindowsCommandAsRuntime(String command) {
List<String> out = new ArrayList<String>();
String[] comm = {
"C:\\Windows\\System32\\cmd.exe",
"/S",
"/K",
"\"" + command + "\"",
"&",
"exit" //devo uscire o il processo CMD resta appeso e non esce l'output
};
String dbg = "";
for (String s : comm)
dbg += s + " ";
System.out.println("COMMAND: " + dbg);
try {
Runtime rt = Runtime.getRuntime();
Process p = rt.exec(comm);
//get the output
out.addAll(
new BufferedReader(new InputStreamReader(p.getInputStream()))
.lines().collect(Collectors.toList()) //the exception is thrown here
);
int exitVal = p.exitValue();
System.out.println("Exited with error code " + exitVal);
p.destroy();
} catch (Exception ex) {
return null;
}
return out;
}
Answered By - Rusu Dinu
Answer Checked By - Marie Seifert (JavaFixing Admin)