How to stop the java application from command prompt gracefully [duplicate] - java

This question already has answers here:
Exiting an application gracefully?
(3 answers)
Closed 3 years ago.
I am developing a java standalone application where it has to upload batch of files to rest api. I want to stop the application whenever I needed from the command prompt but if the application is in the process of uploading a file it has to complete that and has to stop before starting to upload another file.

It cannot stop any time you wish because (I assume) your program runs on a single thread, and thus, must complete every task in the order it is given.
When uploading a list of files, you can provide some kind of listener in the front on one thread while the files upload in the background. When Thread1 recieves the information that it needs to quit, it could then set some kind of global boolean that thread 2 checks before it starts uploading the second file.
Making the upload process a background thread allows you to modify the program in the process.
If you were looking for documentation on gracefully exiting the program in general, it can be found here: http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#exit%28int%29

You could do a quick check on an isUploading flag in your application's exit code JVM shutdown hook. If false, continue with the exit. If true, wait for the upload process to complete or timeout.
See https://stackoverflow.com/a/17792988/2884613.

public class Main {
public static void main(String[] args) {
Runtime r = Runtime.getRuntime();
r.addShutdownHook(new ShutdownHook());
while(Flag.flag){
System.out.println("Application is still running......");
}
if(!Flag.flag) {
System.out.println("goin to exit the application");
Flag.shutdownFlag = false;
return;
}
}
}
public class Flag {
public static boolean flag = true;
public static boolean shutdownFlag = true;
}
public class ShutdownHook extends Thread {
public void run() {
System.out.println("Shutdown hook is initiated");
Flag.flag = false;
while (Flag.shutdownFlag) {
System.out.println("Waiting for application to complete the task..");
}
}
}
I am running the jar in command prompt. As soon as we want to stop the application we can just give ctrl+c in command prompt.

Related

close java process from c# (on windows)

I started a java program from c# by using
...
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WorkingDirectory = "C:\\path\\to\\jar\\";
startInfo.FileName = "C:\\Windows\\Sysnative\\java.exe";
startInfo.Arguments = "-jar JavaProg.jar";
process = new Process();
process.StartInfo = startInfo;
try {
process.Start();
}
...
The process is then running continuously until I want it to stop. The java program has a shutdown hook that should be able to catch normal kill signals. E.g., if I run the jar from a bat script, then pressing Ctrl+c in the cmd window will trigger the shutdown hook, but closing the cmd window will terminate the process without triggering the shutdown hook (similar to End Process in the task manager).
So in order to stop the java program from C# I tried:
process.CloseMainWindow();
or
process.Kill();
The CloseMainWindow method has no effect on the java process, and Kill terminates it without triggering the shutdown hook. So what can I do in order to close the java program gracefully from within the C# code?? [Do I need to make modifications in my Java program to intercept the CloseMainWindow signal? Is there a way to mimic the behavior of Ctrl+c on the cmd window from C#? Must I create some path of communication between my C# and Java codes like a pipe or socket?]
P.S. The C# code is simply a wrapper for the java code in order to run it as a service on windows (I can't use existing tools such as RunAsService for that purpose).
General description of the program:
My java program doesn't create any windows. It has a few threads, the main one runs in a loop just waiting for connections, another performs a specific task on an incoming connection, another thread does periodic updates from a web server, and there's the shutdown hook. Usually, the program is run from the command prompt (or terminal on linux), and takes user input only when it is loading for the first time, after which it can be run again without more user input. The program outputs logs to a file. My shutdown hook:
...
shutdownHook = new ShutdownHook();
Runtime.getRuntime().addShutdownHook(shutdownHook);
...
class ShutdownHook extends Thread {
public void run() {
// log the shutdown is started
// terminate classes
// interrupt and join the other threads
// log the shutdown is done
}
}
The best way of doing this is for your C# program to get a handle to the Java program's stdin. That way, the C# program can send a message to the Java program whenever it likes, and the Java program can listen out for a message asking it to die.
This has the advantage that you don't need to worry about shutdown hooks: the program can do whatever processing it needs to when it receives a shutdown message. It is also a lot more flexible: if, later on, you want the C# program to send other control messages, that can be easily added.
On the Java side, you'd need a separate thread that opens System.in and reads from it, and performs whatever shutdown you need when it gets the right message in.
On the C# side, it looks as though you want
startInfo.RedirectStandardInput = true;
startInfo.UseShellExecute = false;
and then when you want to send a message:
process.StandardInput.WriteLine(...some message...);
(but I am a Java coder, so I am uncertain as to whether I've got the C# right here).
This attempts to close all notepad windows. Note that you can end up getting prompted if you want to save.
[DllImport( "user32.dll", CharSet = CharSet.Auto, SetLastError = false )]
static extern IntPtr SendMessage( IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam );
static uint WM_CLOSE = 0x10;
public void CloseWindow( IntPtr hWindow )
{
SendMessage( hWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero );
}
public void test_close()
{
foreach ( System.Diagnostics.Process p in System.Diagnostics.Process.GetProcessesByName( "notepad" ) )
{
CloseWindow(p.MainWindowHandle);
}
}
You need to use GenerateConsoleCtrlEvent:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683155(v=vs.85).aspx
You can call this using P/Invoke.
This will allow you to generate a Ctrl+C event which your Java program will handle in the same way as it does if you press Ctrl+C in the command window.
Note: However this will only work if the process has a console. Java initialises the Ctrl+C handler on startup so you need to make sure the program has a console when it starts. You can do this by calling AllocConsole in the calling program to create a console, and the java program will inherit the console.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms681944(v=vs.85).aspx

Schedule a executable file without Windows task scheduler

Is it possible to schedule a executable file to run just before log-off using java?
I am working on a application that needed to send a message to the sever just before the system log-off/shutdown. But I didn't find any method to solve it. If anyone know plz help me.
Thanks in advnce.
As stated in the comments a ShutdownHook is probably what you are searching for.
Short example:
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
// Code to be executed when JVM exits
System.out.println("JVM exit");
}
});
Note that the ShutdownHook will execute whenever the JVM exits. So it will also execute when your program terminates normally.
If you have any further questions comment on this answer.

Java how to persist a process reference so I can run process.destroy()

I want to start a webservice via an executible jar I create (so that I can eventually use procrun to have it start up as a Windows Service). The webservice is currently started via the command line by calling the main method on the class.
Here is my code so far:
public class test
{
private static boolean stop = false;
private static Process process;
public static void start(String[] args)
{
String classpath = "my\\classpath\\test.jar";
ProcessBuilder processBuilder = new ProcessBuilder("C:\\java\\jdk1.6.0_43\\bin\\java",
"-cp", classpath,
"com.test.theJavaWebServiceWithAMainMethod");
try
{
process = processBuilder.start();
}
catch (IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
public static void stop(String[] args)
{
stop = true;
process.destroy();
}
public static void main(String[] args)
{
if (args != null && args.length > 0)
{
String command = args[0];
if ("start".equals(command))
{
start(args);
}
else if ("stop".equals(command))
{
stop(args);
}
}
else
{
throw new IllegalArgumentException("command missing");
}
}
}
Starting works fine. I see the process start in the task manager and I can now pull up the WSDL. However when I go to kill the process via process.destroy() (by calling the main method with the arguemnt stop), I get a null pointer exception I assume because this is a new instance of the jvm so it doesn't know the process from when I called start. Whats the best way to persist this process object or pid or something so when I go to call stop, I can find and kill the webservice (java process) that is running?
You are executing your 'test' program twice, which results in two completely separate program instances, and they have no reference to each other. So when you call the 'test' program with stop command, theprocess variable is null because one was not created in the current program.
Options:
Rewrite your main method to block, waiting for the "stop" command. This would mean the start/stop were not separate asynchronous program executions though. You would start the program, and it would then wait for you to enter a stop command before exiting.
You could devise a way to signal the other application 'remotely' ...even though it's all running on the same machine. This is easy to do via a simple network socket, and is a very common approach. (Checkout Tomcat's start/stop command handling for an example....though it's more complex than you need.) To summarize... once running, the main program listens on a server socket. The subsequent "stop program" connects to that server socket as client to notify the main program it should stop.
You could use underlying OS tools to find and stop the program. See this answer: How to find and kill running Win-Processes from within Java? . It's hard to do cross platform and generically though.
It's not really clear what it is you want to do though and why you are executing your web service as a separate program via ProcessBuilder. Depending on your requirements, perhaps you could instead do something like this:
public void start(String[] args)
{
try
{
com.test.theJavaWebServiceWithAMainMethod.main(args);
}
catch (IOException e1)
{
e1.printStackTrace();
}
}
That would start your service, of course, and then you could control-c to end the program.
Rather than start your runnable jar as you do, you could convert your program to start as a Windows Service. Then it would be able to react to a Windows-based shutdown request.

Unable to catch interrupt in java command line program [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java: How could I “intercept” Ctrl+C in a CLI application?
On Windows I start a java non gui application doing a task
Then press CNTL-C and the program just exits, none of my interrupt handling code seems to trigger, even putting a try/catch in the main method never displays a stack trace to indicate it has been interuppted.
public static void main(final String[] args) throws Exception
{
try
{
CmdLineDecoder cld = new CmdLineDecoder();
cld.start(args);
System.exit(0);
}
catch(Exception e)
{
e.printStackTrace();
throw e;
}
}
I'm clearly misunderstanding the effect of Cntl-C, but what ?
You can't do general signal handling in java, but you can handle Ctrl-c.
If you need to do something upon VM shutdown, use a shutdown hook: Runtime.addShutdownHook.
From the docs:
The Java virtual machine shuts down in response to two kinds of events:
The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.
I've used this in the past on Windows/OSX.

Java input without pausing

How would I make a sort of console for my program without pausing my code? I have a loop, for example, that needs to stay running, but when I enter a command in the console, I want the game to check what that command was and process it in the loop. The loop shouldn't wait for a command but just have an if statement to check if there's a command in the queue.
I'm making a dedicated server, by the way, if that helps.
Have them run in two separate threads.
class Server {
public static void main(String[] args) {
InputThread background = new InputThread(this).start();
// Run your server here
}
}
class InputThread {
private final Server server;
public InputThread(Server server) {
this.server = server;
}
public void run() {
Scanner sc = new Scanner(System.in);
while(sc.hasNextLine()) {
// blocks for input, but won't block the server's thread
}
}
}
There's pretty obvious approach: use a dedicated thread to wait on InputStream, read events/commands from it and pass them into a queue.
And your main thread will be regularly checking this queue. After every check it will either process a command from the queue or continue what it was doing if it's empty.
What you'd like to have is a thread in which you keep the command reading code running. It'd probably look something like this:
class ReadCommand implements Runnable
{
public void run()
{
// Command reading logic goes here
}
}
In your "main" thread where the rest of the code is running, you'll have to start it like this:
new Thread(new ReadCommand())).start()
Additionally, you need a queue of commands somewhere which is filled from ReadCommand and read from the other code.
I recommend you to read a manual on concurrent java programming.
The server should run in its own thread. This will allow the loop to run without pausing. You can use a queue to pass commands into the server. Each time through the loop the server can check the queue and process one or more commands. The command line can then submit commands into the queue according to its own schedule.
You can read from the console in a separate thread. This means your main thread doesn't have to wait for the console.
Even server applications can have a Swing GUI. ;)

Categories

Resources