Java: using system parameters vs "regular" command line options - java

Let us assume a Java application, accepting an integer command line argument, say bubu.
Assuming one uses a decent command line parser (and I do - https://github.com/jopt-simple/jopt-simple) plus keeping in mind the -D java switch, these are some of the typical ways to pass this command line parameter:
--bubu 5 (or --bubu=5 or --bubu5)
-Dbubu=5
Where the first one is the program argument and must be handled by the application using some command line parser, whereas the second is the VM argument and is already parsed by java, making it available as Integer.getInteger("bubu")
I am kinda puzzled. What should I use? Using the system property facility:
seems to cost nothing
does not depend on any command line parser library
provides convenient (albeit unexpected) API to obtain the values
As far as I can see, the only cons is that all the command line options have to use the -D flag.
Please, advice.
Thanks.
EDIT
Another pros for the system parameters - "they're usable even when the application is not a stand-alone app starting from a main, but also when the app is a webapp or a unit test." - thanks https://stackoverflow.com/users/571407/jb-nizet
EDIT2
Let me be more focused here. Is there any serious reason (besides esthetics) not to use the system parameters, like always?
EDIT3
OK, I think I get it now. If my code is likely to be loaded by a web application, then there is an issue of a potential name clash, since other web applications hosted by the same web container share the system property space with my code.
Therefore, I have to be prudent and disambiguate my system properties beforehand. So, no more bubu, it is com.shunra.myapp.bubu now. Meaning that instead of a simple
-Dbubu=5
I have
-Dcom.shunra.myapp.bubu=5
which becomes less attractive for a simple command line application.
Another reason is given by Mark Peters, which is pretty good to me.

I'd argue that the advantage Fortyrunner cites is actually the most significant negative for system properties--they are available to anyone who asks for them.
If the flag or option is meant to be a command-line option, it should be available to the layer or module of your code that deals with taking input from the command line, not any code that asks for it.
You can get some destructive coupling from global state, and system properties are no different than any other global state.
That said, if you're just trying to make a quick and dirty CLI program, and separation of concerns and coupling is not a big concern for you, system properties give you an easy method that however leads to (IMO) poor user experience. Some getopt library will give you a lot more support for building a good CLI user experience.

One of the main advantages of system properties is that they are available at any time during the life of you program.
Command line arguments are only available in the main method (unless you persist them).

I feel that there are many things that an average user like me do not need to know. System properties will help the developer of a system preset a number of value that will enable a system to run. For example, when I download GlassFish app server, it always come with many preset parameters that I have no ideas what they're for. I am not very experienced at dealing with server's setting. If you ask me to start GlassFish server with 20 parameters in the command line, I would have to learn what these parameters are for and how much should I set, etc. It's too troublesome.
In brief, when a system gets larger and larger, it may have more and more properties. With system properties preset, users may only need to know what they are when they really need to. For example, I only need to know about GlassFish's -XX:PermSize when I need to increase memory.

Related

Set default memory limit for all applets

Short version
How do I configure the icedtea-plugin package for ubuntu precise in such a way that it executes all applets with a specific memory limit by default? Preferrably using command line tools and no graphical user interface.
Long version
I'm building a kiosk setup using java applets, and would like to increase the default memory limit for all these applets. The kiosk is based on ubuntu linux, using the icedtea-plugin package as a browser plugin. As building the kiosk is automated and headless, I'd rather configure it from the command line if possible.
Here is what I've found out so far:
I'll probably have to specify a -Xmx… command line argument which will be used when starting the java virtual machine for the plugin.
It is possible to pass such arguments using a parameter in the HTML code, i.e.
<param name="java_arguments" value="-Xmx…">.
But that would mean modifying all my HTML files, which I'd rather avoid. And there is a good chance that I'd have to sign my code to make this work, which adds quite a lot of problems in other places of my project.
On my desktop system, using the Oracle VM, there is an application ControlPanel which I can use to set these command line switches. It seems that the configuration gets written to a file ~/.java/deployment/deployment.properties, where it is associated with the key deployment.javaws.jre.0.args.
That key name is not described in the specs for that file. The number 0 seems to refer to one specific JVM, as represented in one row of the table in the control panel. For each JVM, there are several values besides this args value, all sharing a common index number.
According to this wiki section, IcedTea supports a similar file, located at ~/.icedtea/. Not sure whether that means ~/.icedtea/deployment.properties or rather ~/.icedtea/deployment/deployment.properties. IcedTea does not seem to come with a ControlPanel.
As you can see, there are many hints as to how this might work, but so far I haven't seen any definite answer as to what will work. There are still many open questions:
Do I have to create this icedtea deployment file?
Do I have to include a directory named deployment in the path?
Which is the minimal set of keys that I need to specify to make this file work as intended?
Is the args value even supported by OpenJDK, even if it is not described in the corresponding specification?
I guess I could try out all possible combinations to see whether one of them works, but doing so will take considerable time. So I'm asking here, to see if someone has experience in this, and can provide a quiecker answer. If not, I guess I'll answer my own question eventually, once I've tried things the hard way.
as oracle says: http://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-Desktop/html/plugin.html.
following environment variable should be set to add additional arguments to applets:
_JPI_VM_OPTIONS=-Xmx…
Moreover as the reffered site says:
Please note that you need to restart your browser after you set the environment variable. If you are setting this environment variable in the command shell, then you must use the same command shell to launch the browser so that the browser inherits the value of environment variable.
However if you doubt how to set environment variable in ubuntu, following post might be helpful: Make $JAVA_HOME easily changable in Ubuntu
I just had a look at the source code of the icedtea-web plugin. The part of the code which builds the command line seems to have no provision at all for including custom arguments, no matter their origin. So it does not matter which config files, HTML files or environment variables I edit, the code there will build the same command line to call java, disregarding all my whishes.
So if all configuration fails, what remains is hackery. One approach would be to patch the source code of the plugin, and make it include additional words into its command line. For a static addition, i.e. a single size change, this would be fairly easy. A more general fix would include the content of some environment variable, the way Peter's answer suggests. That would mean word-splitting the environment variable in question, and allocating the space for the array of words dynamically. Quite a bit of work at the C level.
As an alternative, one could tackle this at the level of the executed binary. The plugin apparently has the path of the executable hard-coded into it. In my case, this path is /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/java. One can rename that binary to java.orig, and put a shell script in its place, with the following content:
#!/bin/bash
for i in "$#"; do
if [[ "${i}" == sun.applet.PluginMain ]]; then
exec "$0.orig" -Xmx512m "$#"
fi
done
exec "$0.orig" "$#"
One consequence of this approach is the fact that ps will no longer print these applets as java but instead as java.orig. Should not be a problem in most cases.

Is it correct for Java system properties to be used to set and get arbitrary program parameters?

It is possible using -Dproperty=value arguments to set arbitrary system properties (not some fixed set of system properties actually used by the JVM) and a program can get these properties later using System.getProperty("property"). Is it correct to do this?
I haven't found an authoritative answer on this, so that's why I'm asking here. It seems to me that program parameters should be set through command line arguments to the program, not to the JVM. However, perhaps this is an accepted practice that just isn't documented anywhere I've looked so far. I'd like to be sure. Thanks.
I think Java system properties are used to pass values from command line to libraries or plugins inside the execution. It is, that insider component has no direct way to receive the parameter from the main program that's executing it. So it reads it from a "context" that Java system properties are.
If we look at it as layers, command line arguments would be parameters for the inmediate lower layer, and system java properties are context for all the lower layers.
command line: arguments + properties
main program: uses arguments
some library/plugin: uses properties from context
If it's not this way the main program should have to carry all the parameters that user could set to the lower layers and it can be very cumbersome.
I don't like to depend on contextual properties so if I design a program I'd try to pass over all the properties in some non-global way. But it can be very handy some times (and using namespacing it's not probable they collide).
In my opinion this is not "incorrect" and there are programs and libraries that do use their own system properties for configuration.
However, it is probably more practical to put configuration parameters for your software in a configuration file (in whatever format you think is suitable - a .properties file, an XML file, or something else). It is cumbersome, especially if you have many configuration parameters, to have to put all those parameters on the command line with -Dname=value options.
You can use this method to set some of your application settings. I think of settings as a contrast to program arguments. For example. Let's think abount some file converter. It converts file A to B. So files A and B should be command line params. If you converter needs some temporary folder you can make id settable by -Dmy.package.tempfolder=\my\tmp\folder. But there should be a default setting for that and the program should work without this setting.
Think about it as an alternative to .properties file. .properties file will be more convinient of course.
You just have to know what you're doing. If your application is a standalone application, system properties provide an easy to use way to pass named arguments, in any order, to the program, and I don't see anything intrinsically bad in using them.
If your app is a webapp that must be deployed in a app server shared by multiple webapps, then it might not be a good idea, especially if you aren't allowed to change how the server is started, or if you have to deploy multiple versions of the same application.
From http://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html:
For example, the following invocation of getProperty looks up the
System property called subliminal.message. This is not a valid system
property, so instead of returning null, this method returns the
default value provided as a second argument: "Buy StayPuft
Marshmallows!"
System.getProperty("subliminal.message",
"Buy StayPuft Marshmallows!");
This implies that properties other than those used by the JVM are "invalid". However, later in the same document, it gives the example of loading a properties file containing the same property setting.
subliminal.message=Buy StayPuft Marshmallows!
It only advises "In general, be careful not to overwrite system properties."
So it seems that this is a supported use of System Properties. It looks like a case of misleading naming. When I hear "System Properties" I think "properties of the JVM" where the JVM is the system. While the properties are used for this, they can also be used for application settings. I think I'll make a mental note to think of this as "System and Application Properties".
Does anyone disagree with this?

How to tell if a system property comes from human operator, not from default?

I have a JAR-packaged standalone application that, when executed, unpacks itself into a temporal directory and spawns a child process within that directory. The reason being some third-party code and configuration assumes data files are found relative to current working directory, and java has no chdir() method, so the only way is to switch the working dir for a child process.
All works fine, except for the system properties. An operator may decide to specify some system properties in the command line, both standard ones and ones related to the third-party configuration:
java -Djava.io.tmpdir=/temp -Dsomething=else -jar foo.jar (parameters)
The system properties available to the parent java process are not by default propagated to child. I should do it myself. And here I get into a roadblock: I have no way to tell which properties are set by operator and which are initialized by default by JVM.
Take that java.io.tmpdir one. If operator has provided it, he has a good reason to do so (perhaps the default location is "disk full"). I have to set it to child process, or it will fail. But how do I know if it came from operator? It may be just the default value.
I may try and set all available system properties to the child process. It takes a long list though and, worse, fails in some environments where the command line length is limited.
The only workaround I've found so far (quite a wicked one) is to spawn another child process first, with no arguments at all, and let it pipe back to the parent all the system properties it has. The values that match those that parent has are defaults. The rest should be passed down to the worker child process.
Does anyone have a better alternative?
Where I work, we had a slowly growing list of system properties that users could apply, and while we did not have the child process to worry about, we did have a different issue: there were simply too many.
Rather than making the user supply system properties via the command line (or, in our case, making the line in the script that launches the application yet another property longer), we added support for loading a .properties file by default.
If you can convince users to put permanent properties there, then start the process of launching the child process, and then loading from the file, you could avoid the headache altogether.
Still, you would likely be presented with debug scenarios where temporary, or one-time properties are desired without modifying the file (not that it's really a big deal). You have a few choices here:
Continue to use the approach you are currently.
Get the user to pass the system properties as command line arguments that you then load into system properties for both the parent and child process.
Say tough, use the file. (Not a terrible thing, but I would be annoyed with that solution as a user)
I don't think there is a good answer to this. But fortunately, most of the standard system properties either can't be overridden, or nobody in their right mind would override.
So the following approaches are probably your best bets:
pass on the subset of the standard properties that you think that it makes sense to pass on,
provide a way to specify the JVM options (including -D options) to be used for child JVMs, or
a combination of the above approaches.
Chosen solution:
I still had to go with a child process that does nothing but passes the parent all the system properties it gets to compare. The only minor issue I stumbled upon was line.separator property which caused my line reading code stumble on extra empty line. That was easy to fix.
Why I accepted none of answers:
Approaches suggested in the answers below are reasonable, but none of them is completely satisfying.
I do not have much power over the users to tell them that Java system properties should be passed via a property file or a special command-line argument. This is awkward and goes against operational practices (special cases are always bad).
I cannot also select a subset of system properties to pass to the child process. System class documentation doesn't tell which ones are OK to overwrite (and common sense replaces no documentation). There is also a facility for end-user to define their own properties, and those I cannot predict neither by name no number.

Use of AspectJ for debugging Enterprise Java applications

The idea is to utilize AOP for designing applications/tools to debug/view execution flow of an application at runtime. To begin with, a simple data(state) dump at the start and end of method invocation will do the necessary data collection.
The target is not application developers but high level business analyst or high level support people for whom a execution flow could prove helpful. The runtime application flow can also be useful in reducing the learning curve of an application for new developers especially in configuration loaded systems.
I wanted to know if there already exists such tools/applications which could be used. Or better, if this makes sense, then is there a better way to achieve this.
You could start with Spring Insight (http://www.springsource.org/insight) and add your own plugins to collect data appropriate for business analysts/support staff. If that doesn't meet needs, you can write your own custom aspects. It is not that hard.
You could write your own aspects, as suggested by ramnivas, but to prepare for the requests from the users, you may want to just have the aspects compiled into the application, so that you don't have to take a hit at run-time, and then they could just select which execution flows or method groups they are interested in, and you just call the server and set some variable to give them the information desired.
Writing the aspects is easy, but to limit recompiling, you may want to get an idea what the users will want, for example, if they want to have a log of every call made from the time a webservice is called until it gets to the database, then you can build that in, but it would be easier to know this up-front.
Otherwise the aspect does nothing, if the variable is not set, and perhaps unset the variable when finished.
You could also have where they can pick which type of logging and for which user, which may lead to more useful information.

java runtime tracing library to replace system.out.println

Have you heard of any library which would allow me to set up tracing for specific methods at runtime?
Instead of adding (and removing) lots of System.out.println in my code (and having to re-compile and re-deploy) I would like to have a magic thing which would print out a line for each call of selected method without any change in the code. This would work without re-compiling, so some kind of JVM agent (or some non-standard JVM would be needed?). Sounds like a job for aspect programming?
A typical scenario would be to start an application, configure the traced methods dynamically (in a separate file or similar) and then everytime a selected method is called a line with its name (and arguments) is printed out to System.out (or some log file).
Naturally one could think of tens of additional features, but this basic set would be a great tool. BTW, I use Eclipse interactive debugger too, not only the System.out tracing technique, but both have some advantages and sometimes Eclipse is not enough.
Yes what you are referring to is known as Aspect oriented programming. A typical library providing this for Java is AspectJ. You define what are called pointcuts, essentially regular expressions for classes and method names, including wildcards, and the code to execute at each pointcut, known as an advice. This is useful for logging and also security checks and similar cross cutting concerns.
You can turn pointcut advices on and off through configuration. You can have an advice execute before a method call, after it returns or even after it throws an exception. Arguments are also available.
An aspectj java agent is needed for this to work.
In my experience, that kind of very detailed tracing (much more detailed than one would normally use for logging) as a debugging technique is indicative of insufficient unit testing and integration testing.
You can do this using a tool called InTrace.
NOTE: InTrace is a free and open source tool which I have written.
Log4J useful for disabling logging depending on "log-level" (DEBUG, INFO, WARN, FATAL).
You specify in configuration file what the least level you want to appear in logs, e.g., don't log anything below INFO level, and voila!
Looks like there's yet another solution - called Byteman. In their own words:
Byteman is a tool which simplifies tracing and testing of Java
programs. Byteman allows you to insert extra Java code into your
application, either as it is loaded during JVM startup or even after
it has already started running. The injected code is allowed to access
any of your data and call any application methods, including where
they are private. You can inject code almost anywhere you want and
there is no need to prepare the original source code in advance nor do
you have to recompile, repackage or redeploy your application. In fact
you can remove injected code and reinstall different code while the
application continues to execute.
Jackplay is the tool you are looking for.
It allows you to enable logging on method entry and exit points without any coding or redeployment.
It also allows redefining a method body. It gives you web based UI as control panel to enable or undo tracing on your class.methods.

Categories

Resources