Setting runtime system properties programmatically

Seeing as there are problems (I’d like to say bugs, but until I find explicit documentation from Sun on this subject it’s hard to judge…) in java.util.logging’s post-initialization loading of configuration from a different properties file is, but it works OK with the “-D” runtime parameter, is there any way of programmatically filling that runtime parameter PRIOR to the initialization?

Obviously, you can set system properties inside your classes, but this is (it seems) called too late for the logging system (I’m guessing it initializes before then). Equally, you can tell every user that they MUST start java from a command line (Mac OS X users: ?) and that they MUST use your long and complicated command line to start it.

But that’s unacceptable - you completely lose the ability to have an autorunning JAR (no double click, no kernel-loading as an app, no simple “java -jar” command line).

The best I can think of so far is to try setting the system property in the static initializer of a class and keep my fingers crossed that this gets loaded and executed before ANY calls to the logging system. Perhaps if you’re really careful with how you write your code, you can wing it so that your initializer happens before the logging API’s classes are ever referenced, so that (one hopes) it’s identical to a command-line use of -D, as far as that API is concerned?

I thought that perhaps given the number of people around here who try / need to do the same thing (e.g. -Djava.library.path= as frequently used by the various native code OpenGL etc) that someone might have an answer / workaround? And…the fact that it’s used so much means an answer to my problem is likely to help quite a few others in the long run.

I haven’t done this, but I think I remember someone saying you could have your jar file embedded in another jar. The outer jar would contain a Class that would, in the main() with help from the System Class, call a .bat that could run your inner jar with all the parameters desired. I don’t know if that’s too complicated or too easy to work, but for some reason it’s in the back of my mind as a solution. Good luck! :slight_smile:

It’s a hack, but a pretty good idea…although i can see potential problems with profilers, debuggers, etc - maybe attaching to the wrong jvm process ?

But you wouldn’t debug or profile the entire jar, you would only debug or profile the inner jar which contains your game. Thats my understanding anyway…

[quote]But you wouldn’t debug or profile the entire jar, you would only debug or profile the inner jar which contains your game. Thats my understanding anyway…
[/quote]
Ah. Yes. The author would profile the inner one, but… someone who you delivered the complete package to wouldn’t necessarily realise / understand that. Also, some of the developer tools that exist are less than robust in the fact of “weird” deployment/packaging like this, because it’s not something they ever imagined someone doing :). I’m just a little concerned of the consequences - we’ve all seen problems where even the mainstream dev tools fall over when you do things that are a little bit funky.

Or, to put it another way, I’d like to carry on delivering the GrexEngine core libs to customers as self-running JAR’s (some of which actually fire up a GrexEngine server automatically as a form of self-test and/or bootstrap and/or as a precursor to runnign extensive diagnostics; very useful stuff when people are customizing the environment and can easily screw things up - they just run the boot code in the JAR’s, which they have the source for, and use that to work out what they broke in their customized deployment).

…but it’s not going to be me running the debugger, or the profiler, it’s going to be a GE licensee.

Doesn’t this all depend on “which” system properties you’re going to set.

Anything within the standard runtime which is used by default this isn’t possible without what I could only see as a hack round it.

Anything that you’re loading into yourself doesn’t get a chance to access any system properties before you’ve set them. This includes AWT and any third party libraries.

For instance, I set the Java 2D performance properties quite happily as the first thing I do in main(). Since I haven’t done anything to cause Java2D/AWT to be loaded by this point they work quite happily. There are obviously a few properties that are truly “system”, i.e. they’re access instantly as the VM comes up but by the far the majority should be fine to set at the start of main().

Kev

[quote]There are obviously a few properties that are truly “system”, i.e. they’re access instantly as the VM comes up but by the far the majority should be fine to set at the start of main().

Kev
[/quote]
We don’t have control over the main method; that gets written by the developer/licensee. None of the system setup is performed directly in the main method (this is a complex distributed system, after all - it has a reasonably complex and powerful modular “boot” system to handle all that).

The annoying thing is that logging is so fundamental, and is practically the first thing you want to get going. It would be a lot easier if we could just delay referencing logging until we were sure that we’d set the system properties etc.

The other problem is that I don’t know why/how j.u.l screws up its own configuration when you try to config it at runtime. Perhaps there’s some really simple subtlety - like one line of code we should or should NOT have which once corrected will just make it work, but if so then no-one here has spotted it yet. I wish Sun would document their new API’s >:( - 1.4 has been out for years now, and still only two tiny mentions in the java trails. Sob.

[quote]Equally, you can tell every user that they MUST start java from a command line (Mac OS X users: ?)
[/quote]
If you are Mac friendly you will distribute your Java app as a Mac Application Bundle. Inside the bundle there is an XML file that allows you to specify property values.

Of course simple batch files or shell scripts can do the trick too. Even a java app that just execs another java command to launch the main app can do the trick. With clever hacks you could probably do this with a signed webstart app… by finding at runtime the JAR file and then running a command line that will start the JAR file. No need for an inner JAR… It could be the same JAR.

[quote]I wish Sun would document their new API’s >:( - 1.4 has been out for years now, and still only two tiny mentions in the java trails. Sob.
[/quote]
They should change the Java Trail pages to a Wiki.

Well, personally I’d prefer a Zope Talkback (it’s a bit more specialized with the specific aim of letting users comment on a web page in such a way that the comments are embedded but can be opened/closed by viewers), but yes I agree that it would be an excellent idea to have something in that genre of app instead of a static always-out-of-date-because-Sun-doesn’t-allocate-time-and-manpower-to-fix-it page.

It’s the game server for a game, not the client, so OS-specific bundling is out of the question, as is webstart (most servers are headless these days).

The idea of finding the JAR file name from within webstart sounds interesting…but is it possible to work out the hashing algo it uses for naming directories? (from casual glances it looked non-deterministic). If 1.5 adds anything to let you read the CWD (long suggested / requested, but I can’t remember if it’s being included), then it would be easy ;D.

[quote]It’s the game server for a game, not the client, so OS-specific bundling is out of the question, as is webstart (most servers are headless these days).
[/quote]
I don’t get it. How is being the server side component at all relevant to the packaging?? (Though currently not practical for Web Start perhaps.)

[quote]The idea of finding the JAR file name from within webstart sounds interesting…but is it possible to work out the hashing algo it uses for naming directories?
[/quote]
I’m guessing you won’t need to if you use something like

URL url = MyClass.class.getClassLoader().gerResource("something in the jar");

and parse the URL which should be of the form “jar:…”

Apart from being headless, server admins seem to want java code to be identical from OS to OS. Since there’s no fancy GUI to worry about, and no idiot user, and the admins/users are advanced java devs, many of the nice crutches you put in for clients delivered to a mass market are unnecessary - and in the case where you have multiple servers running different OS’s, they can be a distraction.

What we have at the moment is:

  • no-one using OS X as a server (I know it’s possible but at the moment it’s a tiny niche in the world of co-lo and dedicate servers), so possibly some aspects of the packaging would break on OS X (I don’t know!)
  • a product for which licensees can create a single install procedure that is OS independent, because it is all delivered using only x-platform java features. Essentially, you just fire up a single JAR to test the system works. As a developer, you then build a custom JAR to launch your server (or you can use the pre-built ones supplied that setup generic gameservers) that does the same thing. Nice and simple (NB: all config is handled by a dedicated sub-system, since there’s a LOT of config to do, and a lot of it is predicated / dynamic; so long as you can start up the base javaserver, it will automatically “boot” itself from the relevant config subsystems [there’s more than one, for different kinds of config])

Ah, you are far too cunning for me :D. I’ve never debugged a webstarted-app-generated URL to check, but I take it they can’t be purely relative (i.e. your technique should work) because they need to reference multiple JAR’s and extensions all of which will potentially be in different hashed directories?

[quote]Ah, you are far too cunning for me :D. I’ve never debugged a webstarted-app-generated URL to check, but I take it they can’t be purely relative (i.e. your technique should work) because they need to reference multiple JAR’s and extensions all of which will potentially be in different hashed directories?
[/quote]
Yes, resources will be in different folders of the Web Start cache. It’s up to the implementation of course, but the Web Start launcher must manage the classpath so that all the needed resources are accessible via the classpath. I’m not sure what to expect from that hack in terms of a URL… but I suspect that it will be okay. For a moment I thought there might be a security implication if you could get path information from the machine without being signed. I doubt it, but even so you would need to have the app signed to exec the “real code” with the standard java launcher. In fact it is much more likely that you won’t be able to reliably find the launcher, since the ‘java’ command doesn’t have to be in the path. That would lead to trying to guess the location of the ‘java’ executable based on examining the bootclasspath or other properties… it is sure to become loads of fun ;). Let me know when you have it all figured out :stuck_out_tongue:

I know that this is not a real solution, but the vm picks up the properties set in env. variable _JAVA_PROPERTIES.

So if somehow the installer for your app would set that global env. variable (or, alternatively, you set it manually on all target systems =)…

[quote]I know that this is not a real solution, but the vm picks up the properties set in env. variable _JAVA_PROPERTIES.
[/quote]
That would certainly be a slight improvement, in that we could write it in to the installation instructions as a single step that - once done - can be forgotten about. Unfortunately, we don’t have an installer per se.

At the moment we’re still pounding on log4j trying to assess the performance, but we’ll be moving on to j.u.l and having another go at all this soon. Thanks.

I’ve read some blabber about starting more than one jvm and that gives me an idea. Could you load up an initial Class with Webstart that sets those properties, then kills itself (hehe) and calls for a new JVM to be started with your main Class?