0

Assume I've timer task running and creates a new resource on load as demonstrated below. It's a monitoring process set to run indefinitely and is invoked from inside the jar.

For example.

Main Class

public class MyMain  {

   public static void main(String[] args ) {

     TimerTask task = new MyTimerTask();
     Timer timer = new Timer();
     timer.scheduleAtFixedRate(task,0,30000)

  }

}

Timer Task

class MyTimerTask extends TimerTask  {

  private static final MyResource resource;

  static {
    resource = new MyResource();
  }

  @Override
  public void run() {
       ....
  }

  public void close() {
     resource.close();
  }

}

Question: When I stop the process using command line I would like to make sure the resource close method is called. What changes do I need to make ?

I have looked at current solutions ranging from shutdown hook to JMX but I can't decide which one to go with. As I read all solutions it looks to me there is not a clean solution for shutting down the resources in this setup but would like to know the preferred way.

Let me know if you need further details.

s7vr
  • 73,656
  • 11
  • 106
  • 127
  • Use `TimerTask.cance()`? – markspace Oct 16 '18 at 22:47
  • Why is it so important to close this resource? Writing files that can get inconsistent? A shutdownhook should cover all usual scenarios and SIGKILL is something you shouldn't expect because it's bad for consistency of data (that's why databases need very low level filesystem access and flush & sync in specific ways). Get rid of that in your system if it's something that happens regularly (more ram of you oom, ...). Maybe you can approach this differently, because even if you could fix this, you still have the possibility that the system loses power or resets – zapl Oct 16 '18 at 23:47

1 Answers1

1

One way to do it would be to register a new shutdown hook thread using Runtime.addShutdownHook. It will cover regular shutdown scenarios like SIGINT received.

public static void main(String[] args) {
  TimerTask task = new MyTimerTask();
  Timer timer = new Timer();
  timer.scheduleAtFixedRate(task, 0, 1000);

  Runtime.getRuntime().addShutdownHook(new Thread(MyTimerTask::close));
}

public static class MyTimerTask extends TimerTask {

  public static void close() {
    resource.close(); 
  }

}

Since there are always situations when JVM will exit abruptly, e.g. SIGKILL which can't be handled by design, there will be no perfect way to close the resources. As advised in this answer one could use a wrapper script to look for JVM disappearing:

#!/usr/bin/env bash

java MyMain
wait
# cleanup resources if needed
Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111