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.
Related
Can Java run directly on hardware (assuming there's enough memory to include the necessary JRE/JVM? If it can, how does System.out.println work? I'd think there's nowhere for that output to go if it's all just on a cpu.
Directly on hardware? I am assuming you mean to ask if Java can run on a micro-controller? The answer is yes. The JVM is a virtual machine which is essentially its own operating system. The JVM was designed to do exactly what your wondering about. The JVM's two primary functions are to allow Java programs to run on any device or operating system, "Write once, run anywhere" and to optimize memory solutions.
To answer your second question. In order to visually see the output of a System.out.println() call one would simply need to provide the micro-controller with a screen. However, in theory the code would still execute without you seeing it being displayed. So one could write a Java applet that prints "hello world" and then load it onto a micro-controller and run it but that's just silly.
EDIT: I assumed you were not asking: "Can you program a micro-controller with Java" Silly of me, the answer is yes you certainly can; however, you wouldn't want too because the JVM is rather large and it would take up a lot of space. That being said, if you are interested take a look at: the STM32 Java-ready micro-controllers or the Renesas RX. Also, you could run a gutted JVM using uJ or NonvoVM.
The short answer is no, due to the JVM and write once run anywhere feature in java, the code is not ran directly on the hardware but within the JVM... THE JVM essentially acts as a middle man between different hardware/OS...if you look to accomplish this then take a look at C++
I have a Java application that needs to run several times. Every time it runs, it checks if there's data to process and if so, it processes the data.
I'm trying to figure out what's the best approach (performance, resource consumption, etc.) to do this:
1.- Launch it once, and if there's nothing to process make it sleep (All Java).
2.- Using a bash script to launch the Java app, and when it finishes, sleep (the script) and then relaunch the java app.
I was wondering if it is best to keep the Java app alive (sleeping) or relaunching every time.
It's hard to answer your question without the specific context. On the face of it, your questions sounds like it could be a premature optimization.
Generally, I suggest you do what's easier for you to do (and to maintain), unless you have good reasons not to. Here are some possible good reasons, pick the ones appropriate to your situation:
For sleeping in Java:
The check of whether there's new data is easier in Java
Starting the Java program takes time or other resources, for example if on startup, your program needs to load a bunch of data
Starting the Java process from bash is complex for some reason - maybe it requires you to fiddle with a bunch of environment variables, files or something else.
For re-launching the Java program from bash:
The check of whether there's new data is easier in bash
Getting the Java process to sleep is complex - maybe your Java process is a complex multi-threaded beast, and stopping, and then re-starting the various threads is complicated.
You need the memory in between Java jobs - killing the Java process entirely would free all of its memory.
I would not keep it alive.
Instead of it you can use some Job which runs at defined intervals you can use jenkins or you can use Windows scheduler and configure it to run every 5 minutes (as you wish).
Run a batch file with Windows task scheduler
And from your batch file you can do following:
javac JavaFileName.java // To Compile
java JavaFileName // to execute file
See here how to execute java file from cmd :
How do I run a Java program from the command line on Windows?
I personally would determine it, by the place where the application is working.
if it would be my personal computer, I would use second option with bash script (as resources on my local machine might change a lot, due to extensive use of some other programs and it can happen that at some point I might be running out of memory for example)
if it goes to cloud (amazon, google, whatever) I know exactly what kind of processes are running there (it should not change so dynamically comparing to my local PC) and long running java with some scheduler would be fine for me
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.
Is there some way to get reasonable (not noticeable) starting times for Java, thus making it suitable for writing command line scripts (not long-lived apps)?
For a demonstation of the issue, take a simple Hello World program in Java and JavaScript (run w/ node.js) on my Macbook Pro:
$ time java T
Hello world!
real 0m0.352s
user 0m0.301s
sys 0m0.053s
$ time node T.js
Hello world!
real 0m0.098s
user 0m0.079s
sys 0m0.013s
There is a noticeable lag with the Java version, not so with Node. This makes command line tools seem unresponsive. (This is especially true if they rely on more than one class, unlike the simple T.java above.
Not likely, only thing you might be able to try is a different implementation of the JVM, but that probably won't change. Most Java apps are (relatively) long lived though and possibly interactive, which means the JVM startup time becomes lost in the noise of normal uses.
Have you actually tried timing a Java command-line app called repeatedly, though? I would expect after the first incarnation for the start-up time to be alleviated somewhat by the library classes being in the file system cache.
That said, yes, the Java platform is not one of the simplest and in any case you're not going to compete with a small native executable.
Edit: as you say that the timings above are for "warmed up" calls, then a possible workaround could be:
write the gubbins of your commands in Java
write a simple local continually running "server" that takes commands and passes them to the relevant Java routines
write a simple native command-line wrapper (or write it in something that's fast to start up) whose sole raison d'ĂȘtre is to pass commands on to the Java server and spit out the result.
This ain't nice, but it could allow you to write the gubbins of your routines in Java (which I assume is essentially what you want) while still keeping the command line model of invocation.
As others have said, the plain answer is just "not really". You can possibly make minor performance improvements, but you're never going to get away from the fact that the VM is going to take a while to start up and get going.
Make sure you haven't got the server VM selected for apps like this - that's one thing that really will increase the start up time.
The only real way round it is to compile Java to native code, which you can do with GCJ - so if you must write these apps in Java and you must have them faster, that might be a route to look down. Bear in mind though it's not that up-to-date and maintenance on it largely seems to be dying out too.
Haven't tried it yet but might be worth looking at nailgun. It will run your Java programs in the same JVM, so after "warming up" should be pretty fast. A "hello world" example goes from taking 0.132s to taking 0.004s
http://www.martiansoftware.com/nailgun/background.html
You can get a small speed-up with class data sharing https://rmannibucau.metawerx.net/post/java-class-data-sharing-docker-startup
A much bigger speedup should come from doing ahead-of-time compilation to a static binary using GraalVM native-image, although it's still tricky to use. A lot of libraries haven't been made compatible.
I have a java program where certain parts are computationally intensive.
I wish to make that part (which essentially generates an image according to some text data) in C/D.
(Multiple instances of the C program might be running at the same time).
Now, I want to be able to track the progress of the C/D program, so the java code
needs to read the status (progess, errors) of the C/D program somehow.
My idea is to use the environment variables in the OS, to store the status, "TIME_LEFT=2h10m42s" sort of.
Questions:
Is this a good idea, or is there something really bad about this design?
Are there some alternatives, (using sockets, stdin/stdout, other)?
EDIT: The Java works as a front-end, so the C/D code should NOT include anything specifically written for Java. The C/D code is essentially a stand-alone program, Java (or other) provides with GUI.
You cannot use environment variables for this, as you cannot communicate environment variables to another program by other than setting it before you start a new process. So you can't run a C program that changes environment variables that your parent java program can see.
Write line based status to stdout in your C (or D) program rather and read it in your java program.
Using environment variables is a bad idea. Environment variables are inherited by new running processes. They aren't register-type variables that you can just pump and access from any process, so to speak :) You could use JNI and keep checking the time remaining in MS on the Java side, or have the C/D code poll the Java code with the time remaining in its loop (I prefer the other way, however).
Well you can do the other way around .From Java to poll the status of execution.On each 5 seconds to call via JNI the status (progress) of the heavy execution.
I agree with Chris Dennett that this is a bad idea. I would avoid JNI - it is a terrific way to introduce subtle bugs that crash your JVM.
I would implement this by creating a C/D HTTP server running on the local host. The server accepts a POST request to /image/ to start creating the image, a long running process. That POST request returns immediately with a token. I would then GET /image/token which would return either the progress information or the image, depending on if it is done or not. Your Java process can then poll the GET /image/token URL.
Instead of using environment variable use JNA. It is easier than JNI and reliable method to communicate with the program. Another approach is you use Message Queue like ActiveMQ for which C API also available and this is open source. It will decouple the application.