I am using the JDI to debug another running java application.
What I do that works:
Run two applications using Eclipse. The debugger is launched with the following VM Options:
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=4000
The other application connects to the socket at port 4000, and follows normal procedures (break points, etc.) to get a value of a Local Variable.
Works properly and gives me that value.
What I want to do now:
Instead of using Eclipse to launch two processes, I launch one in Eclipse, and that Process uses a ProcessBuilder to launch another one with the following arguments:
String[] args1 = {getJavaDir(),"-cp",classpath,"-Xdebug", "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=4000", "processII.Main2"};
ProcessBuilder builder = new ProcessBuilder(args1);
builder.directory(directory);
Process process = builder.start();
The process starts successfully. However, when I try to access it through the first process, I get the following Error:
com.sun.jdi.connect.IllegalConnectorArgumentsException: Argument invalid
Looked this up online, and there is little information about what the Exception is.
I would appreciate any help figuring out what the problem is!
This exception is throw when there is an error on the connector parameters to debug the JVM. I think that your debug parameters must go in the same argument together instead of two separate arguments (put -Xdebug with -Xrunjdwp... on the same argument), try with:
String[] args1 = {getJavaDir(),"-cp",classpath,"-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=4000", "processII.Main2"};
ProcessBuilder builder = new ProcessBuilder(args1);
builder.directory(directory);
Process process = builder.start();
Hope this helps,
You missed this code :import com.sun.jdi.connect.IllegalConnectorArgumentsException;
It depends on the jdk/lib/tool.jar.If you add this jar to you classpath,you can fixout your problem.
Related
In Java, I start one new Process using Runtime.exec(), and this process in turn spawns several child processes.
I want to be able to kill all the processes, and have previously been trying process.destroy() and process.destroyForcibly() - but the docs say that destroyForcibly() just calls destroy() in the default implementation and destroy() may not kill all subprocesses (I've tried and it clearly doesn't kill the child processes).
I'm now trying a different approach, looking up the PID of the parent process using the method suggested here and then calling ps repeatedly to traverse the PIDs of child processes, then killing them all using kill. (It only needs to run on Linux).
I've managed the first bit - looking up the PID, and am trying the following command to call ps to get the child PIDs:
String command = "/bin/ps --ppid " + pid;
Process process = new ProcessBuilder(command).start();
process.waitFor();
Unfortunately the 2nd line above is throwing an IOException, with the following message: java.io.IOException: Cannot run program "/bin/ps --ppid 21886": error=2, No such file or directory
The command runs fine if I paste it straight into the terminal on Ubuntu 16.04.
Any ideas would be very much appreciated.
Thanks
Calling the command you wish to run this way is always destined to fail.
Since Process does not effectively run a shell session, the command is basically handed over to the underlying OS to run. This means that it'll fail, since the path to t he program to be executed (in this case ps), is not the full one hence the error you're getting.
Also, testing whether your command works using a terminal is not correct. Using a terminal contains the notion of performing an action with an active logged in user with a correct path etc etc. All the above are not the case though when running a command through Process as these are not taken into consideration.
Furthermore, you also need to account for cases where the actual java application could be running under a different user, with a different set of permissions, paths etc.
In order for your to fix this, you can simply do either of the following:
1) Invoke your ps command using the full path to it (still not sure if it would work)
2) Change the way your create the Process object into something like: p = new ProcessBuilder("bash", "-c", command).start();
The second, will effectively run a bash session, passing in the ps command as an argument thus obtaining the desired result.
http://commons.apache.org/proper/commons-exec/tutorial.html
```
String line = "AcroRd32.exe /p /h " + file.getAbsolutePath();
CommandLine cmdLine = CommandLine.parse(line);
DefaultExecutor executor = new DefaultExecutor();
int exitValue = executor.execute(cmdLine);
```
I have a Master.java class which is spawning two types processes (Server.java and Client.java) like this:
To start an process from Server.java (which has a main)
String[] servercmd = {"java", "Server"}
ProcessBuilder pb = new ProcessBuilder(servercmd);
pb.inheritIO();
Process p = pb.start();
To start an process from Client.java (which has a main)
String[] servercmd = {"java", "Client"}
ProcessBuilder pb = new ProcessBuilder(servercmd);
pb.inheritIO();
Process p = pb.start();
Once it starts to run I get errors like this:
Error: Could not find or load main class Server
Error: Could not find or load main class Client
All three of these files Master.java Client.java Server.java are in the same folder.
Does anyone know how to fix this error or how to configure eclipse to handle it?
I don't have the best answer for you on this, but what I would do is use the debugger and step through the process. This way you can see where it is when it's failing. Also, I would check to see that your arguments are allowing you to do more than one argument at a time.
Example: Run this program and have it fail. Within Eclipse click on the 'run' tab at the top, then click 'run configurations'. Look into the 'Arguments' tab and see that you have it set so that each item can be ran at the same time.
Again, I'm not an expert with processbuilder, but it sounds like you are operating more than one item at a time.
So I'm creating a Java program and I want to make it so that you can ask it to open a program.
But, here's the catch, I want the program it opens to be taken from the user input, right now I'm trying to change this
try{Process p = Runtime.getRuntime().exec("notepad.exe");}
catch(Exception e1){}
Into something that opens a program that you asked it to open.
Here's an example of what I want:
User: Can you open chrome?
Program: Of course, here you go!
chrome opens
Could anyone tell me how I would be able to do this?
You can do it in two ways:
1.By Using Runtime:
Runtime.getRuntime().exec(...)
So, for example, on Windows,
Runtime.getRuntime().exec("C:\application.exe -arg1 -arg2");
2.By Using ProcessBuilder:
ProcessBuilder b = new ProcessBuilder("C:\application.exe", "-arg1", "-arg2");
or alternatively
List<String> params = java.util.Arrays.asList("C:\application.exe", "-arg1", "-arg2");
ProcessBuilder b = new ProcessBuilder(params);
or
ProcessBuilder b = new ProcessBuilder("C:\application.exe -arg1 -arg2");
The difference between the two is :
Runtime.getRuntime().exec(...)
takes a single string and passes it directly to a shell or cmd.exe process. The ProcessBuilder constructors, on the other hand, take a varargs array of strings or a List of strings, where each string in the array or list is assumed to be an individual argument.
So,Runtime.getRuntime.exec() will pass the line C:\application.exe -arg1 -arg2 to cmd.exe, which runs a application.exe program with the two given arguments. However, ProcessBuilder method will fail, unless there happens to be a program whose name is application.exe -arg1 -arg2 in C:.
You can try it with like. Pass whole path of where you install chrome.
try{
Process p = Runtime.getRuntime().exec("C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe");
}
catch(Exception e1){
}
When using exec, it is essentially the same as if you were using the command line on windows. Open Command Prompt, type open, and see if it gives details as to how it opens files. If not, find the opener. Usually when dealing with command line operations, there are multiple parameters that are required for opening files/applications. An example of this would be for opening the "TextEdit.app" application on a mac.
Process p = Runtime.getRuntime().exec("open -a TextEdit.app");
Terminal(for mac) would open the app using the -a flag, meaning "application." You could open a file doing:
Process p = Runtime.getRuntime().exec("open filename.file_ext -a TextEdit.app");
The second one will tell the computer to find the application named <app_name>.app and open the file filename.file_ext
I know this is not going to work for a windows machine, but it's only to show how to use the command line operations for opening files and applications. It should be similar for windows though.
Hope this helps
I know that by using the command in the terminal
date --set="2011-12-07 01:20:15.962"
you would actually be able to change the System clock, so I tried it in Java and came up with the following statement
Process p = Runtime.getRuntime().exec("date --set=\"2011-12-07 01:20:15.962\"");
but it was not able to set the clock.
Do you have any idea guys how it may be able work?
Premise:
The machine is Slackware,
The privilege is root level
There are two problems with this line of code:
Process p = Runtime.getRuntime().exec("date --set=\"2011-12-07 01:20:15.962\"");
You did not wait for the process to complete (see also http://docs.oracle.com/javase/6/docs/api/java/lang/Process.html#waitFor())
Parameters should be separated from program name, try this:
"date", "-s", "2011-12-07 01:20:15.962"
Alternatively, invoke shell as the process, and pass in a line of code:
.exec("sh", "-c", "date --set=\"2011-12-07 01:20:15.962\"")
Process p=Runtime.getRuntime().exec(new String[]{"date","--set","2011-12-07 01:20:15.962"});
The above statement worked like magic. #Howard Gou was right with "Parameters should be separated from program name"
The parts of the command statement should be passed by using a String array.
I want to run different commands which can be executed on my command prompt or terminal through Java.
I did search few place but did not get appropriate reply.
I want to run a compiler which is set in the environment as VISAGE_HOME as well as run GRADLE so as to do all my build tasks.
I want to invoke all these commands from within Java Program.
Since it is a swing application I would like to invoke these commands on click of button or some other events.
My Problem is that I am not able to program this :( .
Neither do I know an API which would do this. I went through some sample codes but most of them have same kind of example codes of executing the shell commands or command prompt commands. None showed me to do the above stuff.
Have a look at ProcessBuilder. The Process object it returns has a waitFor method so you can wait for the process to finish. Then you can start your next process.
For example
Process p = new ProcessBuilder("runYourCommand").start();
InputStream in = process.getInputStream();
InputStreamReader inr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(inr);
String inputLine;
while ((inputLine = br.readLine()) != null) {
System.out.println(inputLine);
}
p.waitFor();
Another interesting method on ProcessBuilder is environment(). This will return the environment variables that you can access. From the API docs
Map<String, String> env = pb.environment();
env.put("VAR1", "myValue");
Something like this:
String cmd = "gedit";
Runtime run = Runtime.getRuntime();
Process pr = run.exec(cmd);
Firstly, ProcessBuilder is your friend...
You could have a look at;
Getting started with Java’s ProcessBuilder (Linux focus)
Using ProcessBuilder to Make System Calls
Run processbuilder and get in and output
ProcessBuilder and how redirecting input and output from operating system's processes
Executing Operating System Commands from Java
Secondly, You will need to use System.getenv to find the value of the specified environment variable and substitute it yourself.
nb: Thanks to Guillaume Polet for pointing out that the Process will automatically include the path environment variable to find commands.
Also, remember, DO NOT EXECUTE ANY BLOCKING PROCESS ON THE EDT.
Executing external commands are inherently blocking actions, while not explicitly, taking into account needing to consume the output of the process or wanting to know about the processes termination, these would require you to perform some kind of blocking action. Don't do this on the EDT. It will cause you program to appear as if it's hung.
You can use the Runtime.exec methods to run commands from within Java. The system enviroment variables are normally not visible from within the jvm. You could use a launcher, that submits these system enviroment properties as jvm properties to your java application.
According to http://javarevisited.blogspot.de/2011/02/how-to-execute-native-shell-commands.html implementing the following into your code after including "java.lang.Runtime" should perfectly work:
try {
Process process = Runtime.getRuntime().exec("Command to be executed");
} catch (Exception e) {
e.printStackTrace(System.err);
}