3

I am looking for a general inverse equivalent of the ShutdownHook in Java Runtime i.e. something like a StartupHook where certain custom warmup or setup code can be executed when the JVM first starts up.

I am aware of alternatives like the use of ServletContexts etc. on the startup of Servlet Containers, or such similar features in other frameworks like Spring etc. But these are not what I'm looking for. I am looking for a general JVM solution, if one is available.

Please let me know if the whole idea of a StartupHook would be inadvisable for the JVM and why.

Update: After going through all the answers provided (thanks everyone), it seems that the closest to what I'm looking for is Java Agents.

Although it would be nice (from an ease-of-use point of view but probably not from a security point of view) if the JVM allows me to do something like this:

  1. Write a class that implements StartUpHook with only one method - void preMain()
  2. Put that class into a jar file and put that jar into the classpath or the JRE extensions directory
  3. When JVM starts up, it looks for all classes in the classpath that implements StartUpHook and then calls its preMain() method.
tsaixingwei
  • 636
  • 9
  • 13

5 Answers5

3

There is no startup hook in Java. Your choices are (in the order I would recommend them).

  • Use a startup callback feature of the framework you're running in (i.e. Servlets, Spring, etc). This would also include simply having whoever is writing the main method give you a callback.
  • Wrap the main(String[]) method with your own main(String[]) method and then delegate after calling your main from the commandline.
  • Create a java agent library with a Premain-Class definition in your jar manifest then add the agent to the JVM on the command line.

The last two options require you to add or changes things on the command-line.

fejese
  • 4,601
  • 4
  • 29
  • 36
Dev
  • 11,919
  • 3
  • 40
  • 53
  • I am familiar with your choice no. 1 (through use of ServletContexts in Tomcat etc). – tsaixingwei Jul 30 '13 at 01:08
  • Your choice no. 2 is not as relevant to me as I'm writing a library and by the time my library has loaded, the main method has been executed already? – tsaixingwei Jul 30 '13 at 01:09
  • I think what I'm really looking for is choice no.3 = java agents? Reading through the Java docs, it seems that java agents can be automatically started some time are the JVM is initialized, and this can be controlled by some options provided in my library jar's MANIFEST folders. – tsaixingwei Jul 30 '13 at 01:11
  • From an ease of use point of view (and probably not from a security point of view), I wish Java can provide a simple mechanism where is a jar file in the classpath (or extensions directory) contains a class that implements are certain interface (e.g. "StartupHook"), the JVM will immediately executed the "pre-main" method of that class after the JVM has initialized itself. – tsaixingwei Jul 30 '13 at 01:14
2

What's your use case?

The only reason shutdown hooks are useful is because you do not know when the JVM will shut down. Some piece of code could unexpectedly call System.exit, or all of the windows in a GUI could be closed which would terminate the JVM.

On the other hand, you always know when the JVM will be starting up. Put any code you need to be run at startup in your main method.

Jeffrey
  • 44,417
  • 8
  • 90
  • 141
  • fat-finger on the mouse, sorry. – bmargulies Jul 29 '13 at 23:50
  • Possible use case? Say I'm writing a library and I want some code to be run whenever users of my library err.. uses my library and I don't want to require them to explicit call some App.init() or App.start() method. – tsaixingwei Jul 30 '13 at 00:00
  • After some thought, I suppose if that's my use case, I could just add that startup code to some static initialization block in one of my classes in the library. But it would only be called, if the library user explicitly references that class in their code and not upon the loading of the library jar upon JVM startup. – tsaixingwei Jul 30 '13 at 00:08
  • Or for example, in JRE 6 and above, JDBC drivers are automatically loaded by the JVM when the driver jars are available in the classpath without the need to explicitly call Class.forName("jdbc.driver.class") anymore. How do those driver developers make this happen? Is this something baked into the JVM itself specifically for JDBC drivers? How do I make this happen for my library without having to rely on Oracle to provide this? – tsaixingwei Jul 30 '13 at 00:33
  • @tsaixingwei The api docs for DriverManager tell you how. http://docs.oracle.com/javase/7/docs/api/java/sql/DriverManager.html – Dev Jul 30 '13 at 01:52
1

Just write a static initializer block in a class you know is going to be loaded at startup.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • But then what happens if that class is used in a different program that doesn't want whatever startup behavior the "startup hook" provides? – Jeffrey Jul 30 '13 at 00:02
  • Perhaps then, the "startup hook" could check for the existence some certain environment variables or command line properties (e.g. -Dproperty=value)? – tsaixingwei Jul 30 '13 at 00:15
  • Isn't the code in the static initializer block of a class only executed when that class is actually referenced in the caller's code? Is it possible for my library's "startup hook" to be called even when none of its classes are referenced in the caller's code, but just by the library being loaded because it is in the classpath? For example, the "startup hook" will automatically initialize a daemon in the background just by having that library in the classpath? – tsaixingwei Jul 30 '13 at 00:20
  • Static initializers only run when the class is loaded. The class is loaded when it is first referred to by an executing thread or when it is explicitly loaded using the Class or ClassLoader APIs. – Dev Jul 30 '13 at 00:31
  • Looking at other answers in this question, I suppose what I'm actually looking to do is to provide either an agent library or a Java extension. – tsaixingwei Jul 30 '13 at 00:55
  • @Jeffrey Perhaps the class could be made specific to the application, in the same way the 'startup hook' would have been? It's hard to see that as a serious objection, or even a serious question. – user207421 Jul 30 '13 at 00:59
0

See http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html.

You must be an agent library and define a pre-main method.

bmargulies
  • 97,814
  • 39
  • 186
  • 310
  • Errm... I don't control the JVM if I'm writing a library used by other people who are controlling the JVM cause they are the ones who will be writing the 'main' method and loading my library. – tsaixingwei Jul 30 '13 at 00:04
  • Then give them a main method in your library and tell them to call it as the main method. – bmargulies Jul 30 '13 at 00:36
  • See my other comments above pertaining to a use case like the automatic loading of JDBC drivers without the need to explicitly call Class.forName("jdbc.driver.class") anymore in JRE 6 and above. In this case, the user of the driver jars doesn't even need to call any method in the library in order to the driver class to be loaded at JVM initialization time. Of course, this mechanism is enabled by the JVM vendor's implementation of DriverManager. – tsaixingwei Jul 30 '13 at 00:45
  • Essentially, I'm looking for a solution whereby, just by dropping in a jar in the classpath, the user of my library can have certain code executed automatically in the background without requiring them to even make a single reference to any class in my library. – tsaixingwei Jul 30 '13 at 00:52
  • That's not how JDBC works at all. Someone has to touch the class to cause the static methods to run, and it certainly does _not_ run at the very beginning of JVM time. – bmargulies Jul 30 '13 at 01:03
  • Sorry, I'm not very familiar with how JDBC Drivers are actually loaded by the JVM. I'm only going by this excerpt from the DriverManager javadocs: "When the method getConnection is called, the DriverManager will attempt to locate a suitable driver from amongst those **loaded at initialization** and those loaded explicitly using the same classloader as the current applet or application." I understood the "loaded at initialization" part to refer to the mechanism whereby the JDBC Drivers are automatically loaded at JVM initialization (which is incidentally what I'm trying to ultimately achieve) – tsaixingwei Jul 30 '13 at 02:19
  • DriverManager loads JDBC drivers when `getConnection()` is called, not at JVM startup. – Dev Jul 30 '13 at 03:05
0

How about using a static block in the java class where main is invoked. static block in this case will act like a start up hook, unless you want to control jvm level parameters

shreyas K N
  • 155
  • 1
  • 3
  • 12