I am trying to write a Java program that will execute a line of code on the Windows command prompt. I would like to use an external program (7-Zip) to extract some RAR files (it's more complicated than that but it doesn't matter for the problem at hand).
I got the Runtime instance and used the .exec() method. It works fine when I try to extract one archive by itself but when I try to extract many at the same time, the process gets hung up and .waitFor() never returns.
I researched the problem and believe it is being caused by the output the process is producing. It seems that some buffer or another is filling up and locking up the program. I was outlined here. I implemented this solution (except I used an imput stream and directed it to a file) and it did indeed work. However, it seems to take a lot of extra time to write all that completely unnecessary output.
I was wondering if there was a way to trick the BufferedReader into thinking it has written all that is in its buffer without actually writing it?
Thanks for reading all the way to the bottom!
It's not the Java part that is hanging, it is the native application which blocks when it cannot write it's output anymore.
Since you already have the code to make it work in Java, why don't you just stick with that?
The next best option would be to make the external process not produce any output. Maybe there is a "silent" flag? On Linux, you can also pipe to /dev/null, not sure if Windows has an equivalent (I suppose you could pipe into a file).
Related
I was trying to write something that was eventually supposed to look like a bot for NetHack. However I ran into a few problems I have not been able to solve myself so far.
The first reason is that for some odd reason NetHack, and possibly other tty interface programs, doesn't run when simply ran from a ProcessBuilder. I have confirmed that it does however work for other programs (e.g. Notepad++).
I figure that this is because NetHack actually prefers to be run from a terminal and then to use that until it's done, but Java isn't a terminal so it freaks out and dies.
So I decided to try and to build a shell instead and from that run NetHack. However that introduced some other problems.
The first is that when I read the input stream (stdout) instead of returning -1 or anything at all when there is nothing to read, InputStreamReader.read() simply blocks. This doesn't happen at a predictable position in the terminal, as it does only when the end of the text in the terminal is reached.
The second is that when I try to write something to stdin (not forgetting to flush(), nothing happens. (Tested by trying to write("echo 1") and read()ing the result)
I don't think that there is a solution to the first problem (not involving editing NetHack's source), and I am not sure how to deal with the other two.
(Note: I am actively trying to avoid relying on scripts or pre-existing frameworks)
Any help would be very much appreciated.
EDIT: The last problem was solved by appending System.lineSeperator() (which was to be expected). Also, Java seems to absorb the terminal screen, why does it do that and is there a way to undo that, that would make debugging this a lot easier.
I have problem similar to my previous one presented here.
This time I want use program written in c/c++ to track execution of JAVA program. So as I stated before same code which track stdout printing for c/c++ and register syscall 4 haven't done it for JAVA. I assume it's because execlp which I trace is used just to run jvm. And later on there are created more processes (by inner mechanism of jvm) which I do not track. I found this topic which seems to be partial solution. If I got it right every child will be traced. But that's is a problem as well I want to track only that process which handles my application and not all others that jvm might create. Is there any chance to get know which jvm thread/process handles my program and track only it?
For make it a bit easier let's assume my JAVA program is one-thread.
If you start the binary through your tracer app, all threads will be traced.
But if you attach to a process, then you won't attach to all it's threads. You have to attach to all of its threads using the threadids, that you can found listed eg. in /proc/%d/task/.
Also, I suggest reading through strace's source code, I've learnt a lot from it. If you can use strace to successfully follow java threads as you want, you can get the logic from it.
I'm running Python 2.7 on a Win32 OS, but i'm hoping to write platform-independent code. I'm trying to use Python to interact in real-time with a Java program i wrote, and figured pipes would be the best way to do this. My Python script is calling Java as a subprocess. Essentially, Java is the GUI and Python is the back end. (I don't want to use Jython or wxPython because i only want to be dependent upon the standard libraries each language provides.) Trying to set up communication between the two has been terrible. I can send a message from the (parent) Python script to the (child) Java class using
process.stdin.write(msg)
process.stdin.flush()
but reading Java's output has not worked. I use
process.stdout.read()
but apparently this blocks forever if there's nothing to read. And process.communicate() is off limits because it doesn't do anything until the subprocess terminates. According to my research, a common method people use to get around this problem is to "use threads" (although someone suggested appending a newline when writing -- didn't work), but being new to Python and threading in general i have no idea how that would look. I've tried looking over the standard library's subprocess.py source but that hasn't helped. Is there a way to see if stdout is empty, at least? If not, how do i accomplish this?
process.stdout.read()
but apparently this blocks forever if there's nothing to read.
well not exactly, it will basically block while its either reading/waiting until it hits EOF which is set when the file closes, one way to circumvent this is by stating how many bytes you want to read process.stdout.read(1) this will read 1 byte and return if theres no byte then again it will wait until theres at least one byte or EOF.
You may also use python select module which has an optional timeout period where select waits for this long or simply returns with empty values http://docs.python.org/library/select.html
though it may not be fully supported on windows.
(although someone suggested appending a newline when writing -- didn't work)
I've actually done this though from/to python, coupled with process.stdout.readline().rstrip() so data is a set of line(s) though you still have to strip them, due note you may have to flush in order for both processes to register the data.
I did find this java: how to both read and write to & from process thru pipe (stdin/stdout) which may help you.
good luck.
I've got a (fairly typical) setup at the moment of launching my Java application through a batch file calling the jar file with appropriate parameters, which most of the time works absolutely fine. However, I'd like to be able to deal with any errors that might occur nicely.
At the moment I've got something like
java -Xms1024m -Xmx1024m -jar Quelea.jar
IF NOT (%ERRORLEVEL% == 0) cscript MessageBox.vbs "Application failed to start."
The last line is basically the first answer on this question.
I'd like something a bit more fully featured though, even if it's a case of capturing the output from launching the process and then dumping it in the message box (ok, it's not pretty but it shouldn't appear to start with and when it does appear that then gives me some immediate debugging information without having to ask the user to grab out log files!) Or are there any other approaches that people use in similar situations?
I'm not talking about exceptions thrown in my code (which I deal with once the application starts) I'm talking about hard errors that prevent it starting such as using an old JRE version, not having enough memory to reserve for heap, that sort of thing.
I suggest using a Java executable wrapper. I like the following, but there are others.
http://launch4j.sourceforge.net/
I've a bash script that sequentially calls a java program. That's a bit tricky but mainly what i do is to have a loop and executes about 1500 times the same java program with different arguments.
My question is, when using java 1.5 (the sun VM), each time I'm calling the java program a new instance of the jvm is created ? (I'm not sure that's the right vocabulary...)
Should I avoid this situation by introducing a level of indirection, i.e building a list of all the parameters and then executing one java program which takes these parameters and executes what was previously my entry point ?
Or can I deal with the problem by configuring the JVM as resident or something like that and dynamically invokes my program....
hope this is clear....
thx...
You could save the parameters into a file and use the Java program to process it without constant restart. You could also pipe in the parameters into the running Java app through the console, similarly as for example ls | grep java
Edit: And for the first question. I doubt the java runtime would stay deliberately in memory. Probably most JRE files would remain in the disk cache anyway. On Windows there is a Java Quick Start service which keeps the JRE files around to reduce the startup time for a java program. Don't know whether there is a similar thing for *nix.
Obviously having all the parameters beforehand and running the program once after that would be the best solution. If you cannot do that for any reason i have a very dirty solution to this. Have your program register a port and listen to it for input. Then simply pass the arguments to that port and have your program handle them as a new instance.
JVM startup is notoriously slow, and it certainly not intended to be done in a loop like that. Unfortunately the only way to avoid this if you are passing command line parameters to the java program is to modify the java program itself in some way to have alternative forms of interaction (either from the console, or a port, or a read a file). Java Quick Start is the only (closest thing to a) solution if the java program cannot be changed.
The real solution is to change the Java program. The most obvious change would be to have your loop write to a file, and then start the java program that would read the file one line at a time. That works if the loop doesn't care about the results from the java program for the next set of parameters.
If it does, then it would really be necessary to understand that relationship to advise on an appropriate solution. The socket solution suggested by Savvas is certain a general purpose solution, but there may be better options, depending on what you need to accomplish.
You can use a launcher like in the answer to
Simultaneously run java programs run on same JVM? to read input line by line and start your program's main() method.